     1                                  ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
     2                                  ; (re-write kernel for test by using previous version without a major defect)
     3                                  ; ****************************************************************************
     4                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.2.0
     5                                  ; ----------------------------------------------------------------------------
     6                                  ; NASM version 2.15 (unix386.s)
     7                                  ;
     8                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     9                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
    10                                  ;
    11                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    12                                  ; (v0.1 - Beginning: 11/07/2012)
    13                                  ;
    14                                  ; [ Last Modification: 26/03/2022 ]
    15                                  ;
    16                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    17                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    18                                  ; <Bell Laboratories (17/3/1972)>
    19                                  ; <Preliminary Release of UNIX Implementation Document>
    20                                  ;
    21                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    22                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    23                                  ;
    24                                  ; ****************************************************************************
    25                                  
    26                                  ; 24/12/2013
    27                                  
    28                                  ; Entering protected mode:
    29                                  ; Derived from 'simple_asm.txt' source code file and 
    30                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    31                                  ; (gregor.brunmar@home.se)
    32                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    33                                  ;
    34                                  
    35                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    36                                  ; by Michael Chourdakis (2009) 
    37                                  ; http://www.codeproject.com/Articles/45788/
    38                                  ; http://www.michaelchourdakis.com
    39                                  ;
    40                                  
    41                                  ; Global Descriptor Table:
    42                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    43                                  ; by Linus Torvalds (1991-1992)
    44                                  ;
    45                                  
    46                                  KLOAD	equ 10000h ; Kernel loading address
    47                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    48                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    49                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    50                                  ; 19/03/2015
    51                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    52                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    53                                  ; 24/03/2015
    54                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    55                                  ; 19/03/2015
    56                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    57                                  		     ; (at the end of the 1st 4MB)
    58                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    59                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    60                                  
    61                                  ; 01/01/2022 (Retro UNIX 386 v1.2)
    62                                  ;; 27/12/2013
    63                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    64                                  
    65                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    66                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    67                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    68                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    69                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    70                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    71                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    72                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    73                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    74                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    75                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    76                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    77                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    78                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    79                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    80                                  ;----------------------------------------
    81                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    82                                  ;-----------------------------------------------------------------------------
    83                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    84                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    85                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    86                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    87                                  
    88                                  ; Memory Allocation Table Address
    89                                  ; 05/11/2014
    90                                  ; 31/10/2014
    91                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    92                                  					; the 1st 1 MB memory space.
    93                                  					; (This address must be aligned
    94                                  					;  on 128 KB boundary, if it will be
    95                                  					;  changed later.)
    96                                  					; ((lower 17 bits of 32 bit M.A.T.
    97                                  					;   address must be ZERO)).
    98                                  					; ((((Reason: 32 bit allocation 
    99                                  					;     instructions, dword steps)))
   100                                  					; (((byte >> 12 --> page >> 5)))  
   101                                  ;04/11/2014	
   102                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   103                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   104                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   105                                  ;
   106                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   107                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   108                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   109                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   110                                  
   111                                  ; 17/02/2015 (unix386.s)
   112                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   113                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   114                                  ;
   115                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   116                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   117                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   118                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   119                                  
   120                                  
   121                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   122                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   123                                  ;
   124                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   125                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   126                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   127                                  		      ; otherwise it is standard FDPT with physical values 	
   128                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   129                                  		      ; (obsolete for IDE/ATA drives)
   130                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   131                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   132                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   133                                  			; Bit 4 : Reserved. Always 0
   134                                  			; Bit 3 : Set to 1 if more than 8 heads
   135                                  			; Bit 2-0 : Reserved. Alsways 0
   136                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   137                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   138                                  
   139                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   140                                  ; (11 bytes long) will be used by diskette handler/bios
   141                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   142                                  
   143                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   144                                  
   145                                  [ORG 0] 
   146                                  
   147                                  KSTART: ; 01/01/2022
   148                                  
   149                                  	; 12/11/2014
   150                                  	; Save boot drive number (that is default root drive)
   151 00000000 8816[8A6B]              	mov	[boot_drv], dl ; physical drv number
   152                                  
   153                                  	; Determine installed memory
   154                                  	; 31/10/2014
   155                                  	;
   156 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   157 00000007 CD15                    	int	15h	   ; for large configurations
   158 00000009 7308                    	jnc	short chk_ms
   159 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   160 0000000D CD15                    	int	15h
   161                                  	;	   
   162                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   163                                  	;out	70h, al ; select CMOS register
   164                                  	;in	al, 71h ; read data (1 byte)
   165                                  	;mov	cl, al
   166                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   167                                  	;out	70h, al ; select CMOS register
   168                                  	;in	al, 71h ; read data (1 byte)
   169                                  	;mov	ch, al
   170                                   	;      
   171 0000000F 89C1                    	mov	cx, ax
   172 00000011 31D2                    	xor	dx, dx
   173                                  chk_ms:
   174 00000013 890E[246E]              	mov	[mem_1m_1k], cx
   175 00000017 8916[286E]              	mov	[mem_16m_64k], dx
   176                                  	; 05/11/2014
   177                                  	;and	dx, dx
   178                                  	;jz	short L2
   179 0000001B 81F90004                        cmp     cx, 1024
   180 0000001F 7351                    	jnb	short L0
   181                                  		 ; insufficient memory_error	
   182                                  		 ; Minimum 2 MB memory is needed...
   183                                  oom_0: 
   184                                  	; 05/11/2014
   185                                  	; (real mode error printing)
   186 00000021 FB                      	sti
   187 00000022 BE[3600]                	mov	si, msg_out_of_memory
   188 00000025 BB0700                  	mov	bx, 7
   189 00000028 B40E                    	mov	ah, 0Eh	; write tty
   190                                  oom_1:
   191 0000002A AC                      	lodsb
   192 0000002B 08C0                    	or	al, al
   193 0000002D 7404                    	jz	short oom_2
   194 0000002F CD10                    	int	10h
   195 00000031 EBF7                    	jmp	short oom_1
   196                                  oom_2:
   197 00000033 F4                              hlt
   198 00000034 EBFD                    	jmp	short oom_2
   199                                  
   200                                  ; 28/11/2021 - Retro UNIX 386 v2 compatibility modification (on v1.1)
   201                                  ; 11/04/2021 - Retro UNIX 386 v2
   202                                  ; ((Real mode messages and buffers must be in the 1st 64K of the kernel))
   203                                  ; 20/02/2017 (TRDOS 386 v2)
   204                                  ; 05/11/2014
   205                                  msg_out_of_memory:
   206 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   207 00000039 496E73756666696369-             db      'Insufficient memory !'
   207 00000042 656E74206D656D6F72-
   207 0000004B 792021             
   208 0000004E 0D0A                    	db	0Dh, 0Ah
   209                                  _int13h_48h_buffer: ; 07/07/2016
   210 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   210 00000059 324D42206D656D6F72-
   210 00000062 79206973206E656564-
   210 0000006B 65642E29           
   211 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   212                                  
   213                                  L0:
   214                                  %include 'diskinit.s' ; 07/03/2015
   215                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
   216                              <1> ; (re-write kernel for test by using previous version without a major defect)
   217                              <1> ; ****************************************************************************
   218                              <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC
   219                              <1> ; Last Modification: 02/01/2022
   220                              <1> 
   221                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   222                              <1> 
   223                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   224                              <1> 
   225                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.2)
   226                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   227                              <1> ;L0:
   228                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   229                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   230 00000072 BA7F00              <1> 	mov	dx, 7Fh
   231                              <1> L1:	
   232 00000075 FEC2                <1> 	inc	dl
   233 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   234                              <1> 			; Phoenix EDD v1.1 - EDD v3
   235 00000079 BBAA55              <1> 	mov	bx, 55AAh
   236 0000007C CD13                <1> 	int 	13h
   237 0000007E 721A                <1> 	jc	short L2
   238                              <1> 
   239 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   240 00000084 7514                <1> 	jne	short L2
   241 00000086 FE06[8D6B]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   242 0000008A 8816[8C6B]          <1>         mov     [last_drv], dl  ; last hard disk number
   243 0000008E BB[106B]            <1> 	mov	bx, hd0_type - 80h
   244 00000091 01D3                <1> 	add	bx, dx	 
   245 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   246                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   247                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   248                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   249                              <1>                          ;            (EDD) ready (DPTE ready)
   250                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   251                              <1>                          ;            (EDD-3)
   252                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   253 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   254 00000098 72DB                <1> 	jb	short L1
   255                              <1> L2:
   256                              <1> 	; 23/11/2014
   257                              <1> 	; 19/11/2014
   258 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   259                              <1> 	; 04/02/2016 (esi -> si)
   260 0000009C BE[8E6B]            <1> 	mov	si, fd0_type
   261                              <1> L3:
   262                              <1> 	; 14/01/2015
   263 0000009F 8816[8B6B]          <1> 	mov	[drv], dl
   264                              <1> 	;
   265 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   266 000000A5 CD13                <1> 	int	13h	
   267 000000A7 7210                <1> 	jc	short L4
   268                              <1> 		; BL = drive type (for floppy drives)
   269                              <1> 		; DL = number of floppy drives
   270                              <1> 		;		
   271                              <1> 		; ES:DI = Address of DPT from BIOS
   272                              <1> 		;
   273 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   274                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   275                              <1> 	; 14/01/2015
   276 000000AB E8BB01              <1> 	call	set_disk_parms
   277                              <1> 	; 10/12/2014
   278 000000AE 81FE[8E6B]          <1> 	cmp	si, fd0_type
   279 000000B2 7705                <1> 	ja	short L4
   280 000000B4 46                  <1> 	inc	si ; fd1_type
   281 000000B5 B201                <1> 	mov	dl, 1
   282 000000B7 EBE6                <1> 	jmp	short L3
   283                              <1> L4:
   284                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   285 000000B9 B27F                <1> 	mov	dl, 7Fh
   286                              <1> 	; 24/12/2014 (Temporary)
   287 000000BB 803E[8D6B]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   288                              <1> 	;ja	L10       ; yes, all fixed disk operations
   289                              <1> 			  ; will be performed according to
   290                              <1> 			  ; present EDD specification
   291                              <1> 	; 02/01/2022
   292 000000C0 7603                <1> 	jna	short L5
   293 000000C2 E99100              <1> 	jmp	L10
   294                              <1> L5:
   295 000000C5 FEC2                <1> 	inc 	dl
   296 000000C7 8816[8B6B]          <1>         mov     [drv], dl
   297 000000CB 8816[8C6B]          <1>         mov     [last_drv], dl ; 14/01/2015
   298 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   299 000000D1 CD13                <1> 	int	13h	; (conventional function)
   300                              <1> 	;jc	L13	; fixed disk drive not ready
   301                              <1> 	; 02/01/2022
   302 000000D3 7303                <1> 	jnc	short L6
   303 000000D5 E98301              <1> 	jmp	L13
   304                              <1> L6:
   305 000000D8 8816[8D6B]          <1>         mov     [hdc], dl ; number of drives
   306                              <1> 	;; 14/01/2013
   307                              <1> 	;;push	cx
   308 000000DC E88A01              <1> 	call	set_disk_parms
   309                              <1> 	;;pop	cx
   310                              <1> 	;
   311                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   312 000000DF 8A16[8B6B]          <1>         mov     dl, [drv]
   313 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   314 000000E6 80FA80              <1> 	cmp	dl, 80h
   315 000000E9 7603                <1> 	jna	short L7
   316 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   317                              <1> L7:	
   318 000000EE 31C0                <1> 	xor	ax, ax
   319 000000F0 8ED8                <1> 	mov	ds, ax
   320 000000F2 8B37                <1>         mov     si, [bx]
   321 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   322 000000F7 8ED8                <1> 	mov	ds, ax
   323 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   324                              <1> 	;jne	L12 ; invalid FDPT
   325                              <1> 	; 02/01/2022
   326 000000FC 7403                <1> 	je	short L7_8
   327 000000FE E95601              <1> 	jmp	L12
   328                              <1> L7_8:
   329 00000101 BF0000              <1> 	mov	di, HD0_DPT
   330 00000104 80FA80              <1> 	cmp	dl, 80h
   331 00000107 7603                <1> 	jna	short L8
   332 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   333                              <1> L8:
   334                              <1> 	; 30/12/2014
   335 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   336 0000010F 8EC0                <1> 	mov	es, ax
   337                              <1> 	; 24/12/2014
   338 00000111 B90800              <1> 	mov	cx, 8
   339 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   340 00000116 8CC8                <1> 	mov	ax, cs
   341 00000118 8ED8                <1> 	mov	ds, ax
   342                              <1> 	; 02/02/2015
   343 0000011A 8A0E[8B6B]          <1>         mov     cl, [drv]
   344 0000011E 88CB                <1> 	mov	bl, cl
   345 00000120 B8F001              <1> 	mov	ax, 1F0h
   346 00000123 80E301              <1> 	and	bl, 1
   347 00000126 7406                <1> 	jz	short L9
   348 00000128 C0E304              <1> 	shl	bl, 4
   349 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   350                              <1> L9:
   351 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   352 0000012F 050602              <1> 	add	ax, 206h
   353 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   354 00000133 88D8                <1> 	mov	al, bl
   355 00000135 04A0                <1> 	add	al, 0A0h
   356 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   357                              <1> 	;
   358 00000138 FE06[8B6B]          <1> 	inc	byte [drv]
   359 0000013C BB[106B]            <1> 	mov	bx, hd0_type - 80h
   360 0000013F 01CB                <1> 	add	bx, cx
   361 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   362 00000144 A0[8D6B]            <1> 	mov	al, [hdc]
   363 00000147 FEC8                <1> 	dec	al
   364                              <1> 	;jz	L13
   365                              <1> 	; 02/01/2022
   366 00000149 7408                <1> 	jz	short L9_10
   367 0000014B 80FA80              <1> 	cmp	dl, 80h
   368                              <1>         ;jna	L5
   369                              <1> 	;jmp	L13
   370                              <1> 	; 02/01/2022
   371 0000014E 7703                <1> 	ja	short L9_10
   372 00000150 E972FF              <1> 	jmp	L5
   373                              <1> L9_10:
   374 00000153 E90501              <1>         jmp     L13
   375                              <1> L10:
   376 00000156 FEC2                <1> 	inc 	dl
   377                              <1> 	; 25/12/2014
   378 00000158 8816[8B6B]          <1> 	mov	[drv], dl
   379 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   380 0000015E CD13                <1> 	int	13h	; (conventional function)
   381                              <1> 	;jc	L13
   382                              <1> 	; 02/01/2022
   383 00000160 72F1                <1> 	jc	short L9_10
   384                              <1> 	; 14/01/2015
   385 00000162 8A16[8B6B]          <1> 	mov	dl, [drv]
   386 00000166 52                  <1> 	push	dx
   387 00000167 51                  <1> 	push	cx
   388 00000168 E8FE00              <1> 	call	set_disk_parms
   389 0000016B 59                  <1> 	pop	cx
   390 0000016C 5A                  <1> 	pop	dx
   391                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.2
   392                              <1> 	; 04/02/2016 (esi -> si)
   393                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   394                              <1> 	;		 ; at the '_end' of kernel.
   395                              <1> 	;mov	word [si], 30
   396                              <1> 	; 06/07/2016
   397 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   398                              <1> 	; 09/07/2016
   399 00000170 B81E00              <1> 	mov	ax, 001Eh
   400 00000173 8824                <1> 	mov	[si], ah ; 0
   401 00000175 46                  <1> 	inc	si
   402 00000176 8904                <1> 	mov	word [si], ax
   403                              <1>  	; word [si] = 30
   404                              <1> 	;
   405 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   406 0000017A CD13                <1> 	int	13h
   407                              <1>         ;jc	L13
   408                              <1> 	; 02/01/2022
   409 0000017C 72D5                <1> 	jc	short L9_10
   410                              <1> 	; 04/02/2016 (ebx -> bx)
   411                              <1> 	; 14/01/2015
   412                              <1> 	;sub	bx, bx
   413 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   414 00000180 88D3                <1> 	mov	bl, dl
   415 00000182 80EB80              <1> 	sub	bl, 80h
   416 00000185 81C3[906B]          <1> 	add	bx, hd0_type
   417 00000189 8A07                <1> 	mov 	al, [bx]
   418 0000018B 0C80                <1> 	or	al, 80h
   419 0000018D 8807                <1> 	mov 	[bx], al	
   420 0000018F 81EB[8E6B]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   421 00000193 81C3[DA6B]          <1> 	add	bx, drv.status
   422 00000197 8807                <1> 	mov	[bx], al
   423                              <1> 	; 04/02/2016 (eax -> ax)
   424 00000199 8B4410              <1> 	mov	ax, [si+16]
   425 0000019C 854412              <1> 	test	ax, [si+18]
   426 0000019F 7413                <1> 	jz	short L10_A0h 
   427                              <1> 			; 'CHS only' disks on EDD system 
   428                              <1> 			;  are reported with ZERO disk size
   429 000001A1 81EB[DA6B]          <1> 	sub	bx, drv.status
   430 000001A5 C1E302              <1> 	shl	bx, 2
   431 000001A8 81C3[BE6B]          <1> 	add	bx, drv.size ; disk size (in sectors)
   432 000001AC 8907                <1> 	mov	[bx], ax
   433 000001AE 8B4412              <1> 	mov	ax, [si+18]
   434                              <1> 	;mov	[bx], ax
   435                              <1> 	; 02/01/2022 (BugFix)
   436 000001B1 894702              <1> 	mov	[bx+2], ax
   437                              <1> 
   438                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   439                              <1> 	 ; for CHS disks (28/02/2015)
   440                              <1> 	; 30/12/2014
   441 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   442 000001B7 88D0                <1> 	mov	al, dl
   443 000001B9 83E003              <1> 	and 	ax, 3
   444 000001BC C0E005              <1> 	shl	al, 5 ; *32
   445 000001BF 01C7                <1> 	add 	di, ax
   446 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   447 000001C4 8EC0                <1> 	mov	es, ax
   448                              <1> 	;
   449 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   450 000001C8 88CC                <1> 	mov	ah, cl	
   451 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   452 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   453 000001CE AB                  <1> 	stosw		
   454 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   455 000001D1 FEC0                <1> 	inc	al
   456 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   457 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   458 000001D6 AA                  <1> 	stosb
   459 000001D7 8A440C              <1> 	mov	al, [si+12]
   460 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   461 000001DB 31C0                <1>  	xor	ax, ax
   462                              <1> 	;dec	ax	 ; 02/01/2015 
   463 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   464                              <1> 	;xor	al, al	 ; 02/01/2015	
   465 000001DE AA                  <1> 	stosb		 ; reserved
   466 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   467                              <1> 		         ; (do not disable retries, 
   468                              <1> 			 ; more than 8 heads)
   469 000001E1 AA                  <1> 	stosb
   470 000001E2 8B4404              <1> 	mov	ax, [si+4]
   471 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   472                              <1> 	;push	ax	 ; 02/01/2015
   473 000001E6 8A4408              <1> 	mov	al, [si+8]
   474 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   475 000001EA 29C0                <1> 	sub 	ax, ax
   476                              <1> 	;pop	ax	 ; 02/01/2015	
   477 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   478 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   479 000001EF 243F                <1> 	and 	al, 3Fh	
   480 000001F1 AA                  <1> 	stosb
   481                              <1> 	;sub	al, al	 ; checksum
   482                              <1> 	;stosb
   483                              <1> 	;
   484 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   485 000001F5 AD                  <1> 	lodsw
   486 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   487 000001F7 AD                  <1> 	lodsw
   488 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   489                              <1> 	;
   490                              <1> 	; checksum calculation
   491 000001F9 89FE                <1> 	mov	si, di
   492 000001FB 06                  <1> 	push	es
   493 000001FC 1F                  <1> 	pop	ds
   494                              <1> 	;mov	cx, 16
   495 000001FD B90F00              <1> 	mov 	cx, 15
   496 00000200 29CE                <1> 	sub	si, cx
   497 00000202 30E4                <1> 	xor	ah, ah
   498                              <1> 	;del	cl
   499                              <1> L11:		
   500 00000204 AC                  <1> 	lodsb
   501 00000205 00C4                <1> 	add	ah, al
   502 00000207 E2FB                <1> 	loop	L11
   503                              <1> 	;
   504 00000209 88E0                <1> 	mov	al, ah
   505 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   506 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   507                              <1> 	;
   508 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   509 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   510                              <1> 	;
   511                              <1> 	; 23/02/2015
   512 00000210 57                  <1> 	push	di
   513                              <1> 	; ES:DI points to DPTE (FDPTE) location
   514                              <1> 	;mov	cx, 8
   515 00000211 B108                <1> 	mov	cl, 8
   516 00000213 F3A5                <1> 	rep	movsw	
   517                              <1> 	;
   518                              <1> 	; 23/02/2015
   519                              <1> 	; (P)ATA drive and LBA validation
   520                              <1> 	; (invalidating SATA drives and setting
   521                              <1> 	; CHS type I/O for old type fixed disks)
   522 00000215 5B                  <1> 	pop	bx
   523 00000216 8CC8                <1> 	mov	ax, cs
   524 00000218 8ED8                <1> 	mov	ds, ax
   525 0000021A 268B07              <1> 	mov	ax, [es:bx]
   526 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   527 00000220 7418                <1> 	je	short L11a
   528 00000222 3D7001              <1> 	cmp	ax, 170h
   529 00000225 7413                <1> 	je	short L11a
   530                              <1> 	; invalidation 
   531                              <1> 	; (because base port address is not 1F0h or 170h)
   532 00000227 30FF                <1> 	xor	bh, bh
   533 00000229 88D3                <1> 	mov	bl, dl
   534 0000022B 80EB80              <1> 	sub	bl, 80h
   535 0000022E C687[906B]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   536 00000233 808F[DC6B]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   537 00000238 EB14                <1> 	jmp	short L11b
   538                              <1> L11a:	
   539                              <1> 	; LBA validation
   540 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   541 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   542 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   543                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   544 00000242 28FF                <1> 	sub	bh, bh
   545 00000244 88D3                <1> 	mov	bl, dl
   546 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   547 00000249 80A7[DC6B]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   548                              <1> 				; bit 0 = LBA ready bit
   549                              <1> 	; 'diskio' procedure will check this bit !
   550                              <1> L11b:
   551 0000024E 3A16[8C6B]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   552 00000252 7307                <1>         jnb     short L13
   553 00000254 E9FFFE              <1>         jmp     L10
   554                              <1> L12:
   555                              <1> 	; Restore data registers
   556 00000257 8CC8                <1> 	mov	ax, cs
   557 00000259 8ED8                <1> 	mov	ds, ax	
   558                              <1> L13:
   559                              <1> 	; 13/12/2014
   560 0000025B 0E                  <1> 	push	cs
   561 0000025C 07                  <1> 	pop	es
   562                              <1> L14:
   563 0000025D B411                <1> 	mov 	ah, 11h
   564 0000025F CD16                <1> 	int 	16h
   565                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   566                              <1> 	; 02/01/2022
   567 00000261 7466                <1> 	jz	short L16
   568 00000263 B010                <1> 	mov	al, 10h
   569 00000265 CD16                <1> 	int 	16h
   570 00000267 EBF4                <1> 	jmp 	short L14
   571                              <1> L15:
   572                              <1> 
   573                              <1> ; //////
   574                              <1> 
   575                              <1> ; 02/01/2022 - Retro UNIX 386 v1.2
   576                              <1> %if 0
   577                              <1> 	; 24/11/2014
   578                              <1> 	; 19/11/2014
   579                              <1> 	; 14/11/2014
   580                              <1> 	; Temporary code for disk searching code check
   581                              <1> 	;
   582                              <1> 	; This code will show existing (usable) drives and also
   583                              <1> 	; will show EDD interface support status for hard disks		
   584                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   585                              <1> 	; no need to get it again in protected mode...) 
   586                              <1> 	;	
   587                              <1> 	; 13/11/2014
   588                              <1> 	mov	bx, 7
   589                              <1> 	mov	ah, 0Eh
   590                              <1> 	mov	al, [fd0_type]
   591                              <1> 	and	al, al
   592                              <1> 	jz	short L15a
   593                              <1> 	mov	dl, al
   594                              <1> 	mov	al, 'F'
   595                              <1> 	int 	10h
   596                              <1> 	mov	al, 'D'
   597                              <1> 	int 	10h
   598                              <1> 	mov	al, '0'
   599                              <1> 	int 	10h
   600                              <1> 	mov	al, ' '
   601                              <1> 	int	10h
   602                              <1> 	call	L15c
   603                              <1> 	mov	al, ' '
   604                              <1> 	int	10h
   605                              <1> 	;
   606                              <1> 	mov	al, [fd1_type]
   607                              <1> 	and	al, al
   608                              <1> 	jz	short L15a
   609                              <1> 	mov	dl, al
   610                              <1> 	mov	al, 'F'
   611                              <1> 	int 	10h
   612                              <1> 	mov	al, 'D'
   613                              <1> 	int 	10h
   614                              <1> 	mov	al, '1'
   615                              <1> 	int 	10h
   616                              <1> 	mov	al, ' '
   617                              <1> 	int	10h
   618                              <1> 	call	L15c
   619                              <1> 	mov	al, ' '
   620                              <1> 	int	10h
   621                              <1> 	mov	al, ' '
   622                              <1> 	int	10h
   623                              <1> L15a:
   624                              <1> 	mov	al, [hd0_type]
   625                              <1> 	and	al, al
   626                              <1> 	jz	short L15b
   627                              <1> 	mov	dl, al
   628                              <1> 	mov	al, 'H'
   629                              <1> 	int 	10h
   630                              <1> 	mov	al, 'D'
   631                              <1> 	int 	10h
   632                              <1> 	mov	al, '0'
   633                              <1> 	int 	10h
   634                              <1> 	mov	al, ' '
   635                              <1> 	int 	10h
   636                              <1> 	call	L15c
   637                              <1> 	mov	al, ' '
   638                              <1> 	int	10h
   639                              <1> 	;
   640                              <1> 	mov	al, [hd1_type]
   641                              <1> 	and	al, al
   642                              <1> 	jz	short L15b
   643                              <1> 	mov	dl, al
   644                              <1> 	mov	al, 'H'
   645                              <1> 	int 	10h
   646                              <1> 	mov	al, 'D'
   647                              <1> 	int 	10h
   648                              <1> 	mov	al, '1'
   649                              <1> 	int 	10h
   650                              <1> 	mov	al, ' '
   651                              <1> 	int 	10h
   652                              <1> 	call	L15c
   653                              <1> 	mov	al, ' '
   654                              <1> 	int	10h
   655                              <1> 	;
   656                              <1> 	mov	al, [hd2_type]
   657                              <1> 	and	al, al
   658                              <1> 	jz	short L15b
   659                              <1> 	mov	dl, al
   660                              <1> 	mov	al, 'H'
   661                              <1> 	int 	10h
   662                              <1> 	mov	al, 'D'
   663                              <1> 	int 	10h
   664                              <1> 	mov	al, '2'
   665                              <1> 	int 	10h
   666                              <1> 	mov	al, ' '
   667                              <1> 	int 	10h
   668                              <1> 	call	L15c
   669                              <1> 	mov	al, ' '
   670                              <1> 	int	10h
   671                              <1> 	;
   672                              <1> 	mov	al, [hd3_type]
   673                              <1> 	and	al, al
   674                              <1> 	jz	short L15b
   675                              <1> 	mov	dl, al
   676                              <1> 	mov	al, 'H'
   677                              <1> 	int 	10h
   678                              <1> 	mov	al, 'D'
   679                              <1> 	int 	10h
   680                              <1> 	mov	al, '3'
   681                              <1> 	int 	10h
   682                              <1> 	mov	al, ' '
   683                              <1> 	int 	10h
   684                              <1> 	call	L15c
   685                              <1> 	mov	al, ' '
   686                              <1> 	int	10h
   687                              <1> 	;
   688                              <1> L15b:
   689                              <1> 	mov	al, 0Dh
   690                              <1> 	int 	10h	
   691                              <1> 	mov	al, 0Ah
   692                              <1> 	int 	10h
   693                              <1> 	;;xor	ah, ah
   694                              <1> 	;;int 	16h	
   695                              <1> 	;
   696                              <1>         ;jmp	L16  ; jmp short L16
   697                              <1>         ; 02/01/2022
   698                              <1> 	jmp	short L16
   699                              <1> 	;
   700                              <1> L15c:
   701                              <1> 	mov	dh, dl
   702                              <1> 	shr	dh, 4
   703                              <1> 	add	dh, 30h
   704                              <1> 	and	dl, 15
   705                              <1> 	add	dl, 30h
   706                              <1> 	mov	al, dh
   707                              <1> 	int	10h
   708                              <1> 	mov	al, dl
   709                              <1> 	int	10h
   710                              <1> 	retn
   711                              <1> 	;
   712                              <1> 	; end of temporary code for disk searching code check
   713                              <1> 
   714                              <1> %endif
   715                              <1> 
   716                              <1> ; //////
   717                              <1> 
   718                              <1> set_disk_parms:
   719                              <1> 	; 04/02/2016 (ebx -> bx)
   720                              <1> 	; 10/07/2015
   721                              <1> 	; 14/01/2015
   722                              <1> 	;push	bx
   723 00000269 28FF                <1> 	sub	bh, bh
   724 0000026B 8A1E[8B6B]          <1> 	mov	bl, [drv]
   725 0000026F 80FB80              <1> 	cmp	bl, 80h
   726 00000272 7203                <1> 	jb	short sdp0
   727 00000274 80EB7E              <1> 	sub	bl, 7Eh
   728                              <1> sdp0:	
   729 00000277 81C3[DA6B]          <1> 	add	bx, drv.status
   730 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   731                              <1> 	;
   732 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   733 00000280 88CC                <1> 	mov	ah, cl ; 
   734 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   735 00000285 81EB[DA6B]          <1> 	sub	bx, drv.status
   736 00000289 D0E3                <1> 	shl	bl, 1
   737 0000028B 81C3[946B]          <1> 	add	bx, drv.cylinders
   738 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   739 00000290 8907                <1> 	mov	[bx], ax
   740 00000292 50                  <1> 	push	ax ; ** cylinders
   741 00000293 81EB[946B]          <1> 	sub	bx, drv.cylinders
   742 00000297 81C3[A26B]          <1> 	add	bx, drv.heads
   743 0000029B 30E4                <1> 	xor	ah, ah
   744 0000029D 88F0                <1> 	mov	al, dh ; heads
   745 0000029F 40                  <1> 	inc	ax
   746 000002A0 8907                <1> 	mov	[bx], ax
   747 000002A2 81EB[A26B]          <1>         sub     bx, drv.heads
   748 000002A6 81C3[B06B]          <1>         add     bx, drv.spt
   749 000002AA 30ED                <1> 	xor	ch, ch
   750 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   751 000002AF 890F                <1> 	mov	[bx], cx
   752 000002B1 81EB[B06B]          <1>         sub     bx, drv.spt
   753 000002B5 D1E3                <1> 	shl	bx, 1
   754 000002B7 81C3[BE6B]          <1> 	add	bx, drv.size ; disk size (in sectors)
   755                              <1> 	; LBA size = cylinders * heads * secpertrack
   756 000002BB F7E1                <1> 	mul	cx 
   757 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   758 000002BF 58                  <1> 	pop	ax ; ** cylinders
   759 000002C0 48                  <1> 	dec	ax ; 1 cylinder reserved (!?)
   760 000002C1 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   761 000002C3 8907                <1> 	mov	[bx], ax
   762 000002C5 895702              <1> 	mov	[bx+2], dx
   763                              <1> 	;
   764                              <1> 	;pop	bx
   765 000002C8 C3                  <1> 	retn
   766                              <1> 
   767                              <1> ;align 2
   768                              <1> 
   769                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   770                              <1> ;heads	  :  dw 0, 0, 0, 0, 0, 0
   771                              <1> ;spt	  :  dw 0, 0, 0, 0, 0, 0
   772                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   773                              <1> 
   774                              <1> ;last_drv:
   775                              <1> ;	db  0
   776                              <1> ;drv_status:
   777                              <1> ;	db  0,0,0,0,0,0
   778                              <1> ;	db 0
   779                              <1> 
   780                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   781                              <1> 
   782                              <1> L16:
   215                                  _L0:	
   216                                  	; 10/11/2014
   217 000002C9 FA                           	cli	; Disable interrupts (clear interrupt flag)
   218                                  		; Reset Interrupt MASK Registers (Master&Slave)
   219                                  	;mov	al, 0FFh	; mask off all interrupts
   220                                  	;out	21h, al		; on master PIC (8259)
   221                                  	;jmp 	$+2  ; (delay)
   222                                  	;out	0A1h, al	; on slave PIC (8259)
   223                                  	;
   224                                  	; Disable NMI 
   225 000002CA B080                    	mov   	al, 80h 
   226 000002CC E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   227                                  	; 23/02/2015
   228 000002CE 90                      	nop			;
   229                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   230                                  				; for preventing unknown state (!?)
   231                                  
   232                                  	; 01/01/2022 (Retro UNIX 386 v1.2)
   233                                  	%define KERNELFSIZE KEND-KSTART 
   234                                  	;
   235                                   	; 20/08/2014
   236                                  	; Moving the kernel 64 KB back (to physical address 0)
   237                                  	; DS = CS = 1000h
   238                                  	; 05/11/2014
   239 000002CF 31C0                    	xor	ax, ax
   240 000002D1 8EC0                    	mov	es, ax ; ES = 0
   241                                  	;
   242                                  	;;mov	cx, (KEND - KLOAD)/4
   243                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 01/01/2022
   244 000002D3 B91637                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   245 000002D6 31F6                    	xor	si, si
   246 000002D8 31FF                    	xor	di, di
   247                                  	;rep	movsd
   248 000002DA F3A5                    	rep	movsw ; 02/01/2022
   249                                  	;
   250 000002DC 06                      	push	es ; 0
   251 000002DD 68[E102]                	push	L17
   252 000002E0 CB                      	retf
   253                                  	;
   254                                  L17:
   255                                  	; Turn off the floppy drive motor
   256 000002E1 BAF203                          mov     dx, 3F2h
   257 000002E4 EE                              out     dx, al ; 0 ; 31/12/2013
   258                                  
   259                                  	; Enable access to memory above one megabyte
   260                                  L18:
   261 000002E5 E464                    	in	al, 64h
   262 000002E7 A802                    	test	al, 2
   263 000002E9 75FA                            jnz     short L18
   264 000002EB B0D1                    	mov	al, 0D1h	; Write output port
   265 000002ED E664                    	out	64h, al
   266                                  L19:
   267 000002EF E464                    	in	al, 64h
   268 000002F1 A802                    	test	al, 2
   269 000002F3 75FA                            jnz     short L19
   270 000002F5 B0DF                    	mov	al, 0DFh	; Enable A20 line
   271 000002F7 E660                    	out	60h, al
   272                                  ;L20:
   273                                  	;
   274                                  	; Load global descriptor table register
   275                                  
   276                                          ;mov	ax, cs
   277                                          ;mov	ds, ax
   278                                  
   279 000002F9 2E0F0116[B068]                  lgdt    [cs:gdtd]
   280                                  
   281 000002FF 0F20C0                          mov     eax, cr0
   282                                  	;or 	eax, 1
   283 00000302 40                      	inc     ax
   284 00000303 0F22C0                  	mov     cr0, eax
   285                                  
   286                                  	; Jump to 32 bit code
   287                                  	
   288 00000306 66                      	db	66h 		; Prefix for 32-bit
   289 00000307 EA                      	db	0EAh 		; Opcode for far jump
   290 00000308 [0E030000]              	dd	StartPM 	; Offset to start, 32-bit
   291                                  				; (1000h:StartPM = StartPM + 10000h)
   292 0000030C 0800                    	dw	KCODE		; This is the selector for CODE32_DESCRIPTOR,
   293                                  				; assuming that StartPM resides in code32
   294                                  
   295                                  [BITS 32] 
   296                                  
   297                                  StartPM:
   298                                  	; Kernel Base Address = 0 ; 30/12/2013
   299 0000030E 66B81000                	mov	ax, KDATA	; Save data segment identifier
   300 00000312 8ED8                            mov	ds, ax		; Move a valid data segment into DS register
   301 00000314 8EC0                           	mov	es, ax		; Move data segment into ES register
   302 00000316 8EE0                           	mov	fs, ax		; Move data segment into FS register
   303 00000318 8EE8                          	mov	gs, ax		; Move data segment into GS register
   304 0000031A 8ED0                            mov	ss, ax		; Move data segment into SS register
   305 0000031C BC00000900                      mov	esp, 90000h	; Move the stack pointer to 090000h
   306                                  
   307                                  clear_bss: ; Clear uninitialized data area
   308                                  	; 11/03/2015
   309 00000321 31C0                    	xor	eax, eax ; 0
   310                                  	;mov	ecx, (bss_end - bss_start)/4
   311                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   312                                  	; 12/12/2021
   313 00000323 B99A070000              	mov	ecx, BSS_SIZE/4
   314 00000328 BF[306E0000]            	mov	edi, bss_start	
   315 0000032D F3AB                    	rep	stosd  		
   316                                  
   317                                  memory_init:
   318                                  	; Initialize memory allocation table and page tables
   319                                  	;
   320                                  	; 02/01/2022 (Retro UNIX 386 v1.2)
   321                                  	; 16/11/2014
   322                                  	; 15/11/2014
   323                                  	; 07/11/2014
   324                                  	; 06/11/2014
   325                                  	; 05/11/2014
   326                                  	; 04/11/2014
   327                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   328                                  	;
   329                                  ;	xor	eax, eax
   330                                  ;	xor 	ecx, ecx
   331 0000032F B108                    	mov	cl, 8
   332 00000331 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   333 00000336 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   334                                  				   ; for the first 1 MB memory
   335                                  	;
   336 00000338 8B0D[246E0000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   337                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   338                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   339                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   340 0000033E C1E902                  	shr	ecx, 2	; 02/01/2022
   341 00000341 890D[A0700000]          	mov	[free_pages], ecx
   342 00000347 8B15[286E0000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   343                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   344                                  				   ; between 16 MB and 4 GB.
   345                                  	;or	dx, dx
   346 0000034D 09D2                    	or	edx, edx ; 02/01/2022
   347 0000034F 7412                    	jz	short mi_0
   348                                  	;
   349                                  	;mov	ax, dx
   350 00000351 89D0                    	mov	eax, edx ; 02/01/2022
   351 00000353 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   352 00000356 0105[A0700000]          	add	[free_pages], eax
   353 0000035C 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   354 00000361 EB06                    	jmp	short mi_1
   355                                  mi_0:
   356                                  	;mov	ax, cx
   357 00000363 89C8                    	mov	eax, ecx ; 02/01/2022	 
   358 00000365 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   359                                  mi_1:
   360 00000369 A3[9C700000]            	mov	[memory_size], eax ; Total available memory in pages
   361                                  				   ; 1 alloc. tbl. bit = 1 memory page
   362                                  				   ; 32 allocation bits = 32 mem. pages
   363                                  	;
   364 0000036E 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   365 00000373 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   366                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   367                                  				   ;  --> x M.A.T. pages, if y = 0
   368                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   369 00000376 A3[B0700000]            	mov	[mat_size], eax ; 02/01/2022
   370 0000037B C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   371                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   372 0000037E 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   373                                  	; Set/Calculate Kernel's Page Directory Address
   374 00000380 81C300001000            	add	ebx, MEM_ALLOC_TBL
   375 00000386 891D[98700000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   376                                  				   ; just after the last M.A.T. page
   377                                  	;
   378 0000038C 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   379 0000038F A3[A8700000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   380                                  	;			   ; (allocation status search must be
   381                                  				   ; stopped after here)
   382 00000394 31C0                    	xor	eax, eax
   383 00000396 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   384                                  	;push	cx
   385 00000397 51                      	push	ecx ; 02/01/2022 
   386 00000398 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   387                                  				   ; count of 32 allocation bits
   388 0000039B F3AB                    	rep	stosd
   389                                  	;pop	cx
   390 0000039D 59                      	pop	ecx ; 02/01/2022
   391 0000039E 40                      	inc	eax		   ; 0
   392 0000039F 80E11F                  	and	cl, 31		   ; remain bits
   393 000003A2 7412                    	jz	short mi_4
   394 000003A4 8907                    	mov	[edi], eax	   ; reset
   395                                  mi_2:
   396 000003A6 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   397 000003A9 FEC9                    	dec	cl
   398 000003AB 7404                    	jz	short mi_3
   399 000003AD FEC0                    	inc	al
   400 000003AF EBF5                    	jmp	short mi_2
   401                                  mi_3:
   402 000003B1 28C0                    	sub	al, al	   	   ; 0
   403 000003B3 83C704                  	add	edi, 4		   ; 15/11/2014
   404                                  mi_4:
   405 000003B6 09D2                    	or	edx, edx ; 02/01/2022
   406                                  	;or	dx, dx		  ; check 16M to 4G memory space
   407 000003B8 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   408                                  	;	
   409 000003BA B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   410                                  	;	
   411 000003BF 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   412 000003C1 7405                    	jz	short mi_5	  ; jump if EDI points to 
   413                                  				  ;         end of first 16 MB	
   414                                  	;shr	ecx, 1		  ; convert to dword count
   415                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   416 000003C3 C1E902                  	shr	ecx, 2	; 02/01/2022
   417 000003C6 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   418                                  				  ; (memory hole under 16 MB)
   419                                  mi_5:
   420 000003C8 89D1                    	mov	ecx, edx ; 02/01/2022
   421                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   422 000003CA D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   423 000003CC 9C                      	pushf			  ; 16/11/2014		
   424 000003CD 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   425 000003CE F3AB                    	rep	stosd
   426 000003D0 40                      	inc	eax		  ; 0
   427 000003D1 9D                      	popf			  ; 16/11/2014
   428 000003D2 7305                    	jnc	short mi_6
   429 000003D4 6648                    	dec	ax		  ; eax = 0000FFFFh
   430 000003D6 AB                      	stosd
   431 000003D7 6640                    	inc	ax		  ; 0		
   432                                  mi_6:
   433 000003D9 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   434 000003DB 7309                    	jnb	short mi_7	  ; end of memory allocation table
   435                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   436 000003DD 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   437 000003DF 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   438                                  	;shr	ecx, 1		  ; to dword count
   439                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   440 000003E1 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   441 000003E4 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   442                                  mi_7:
   443                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   444 000003E6 BA00001000              	mov	edx, MEM_ALLOC_TBL
   445                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   446                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   447 000003EB 8B0D[B0700000]          	mov	ecx, [mat_size] ; 02/01/2022
   448                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   449 000003F1 89D7                    	mov	edi, edx
   450 000003F3 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   451                                  				  ; byte offset in M.A.T.
   452                                  				  ; (1 M.A.T. byte points to 
   453                                  				  ;	      32768 bytes)
   454                                  				  ; Note: MEM_ALLOC_TBL address 
   455                                  				  ; must be aligned on 128 KB 
   456                                  				  ; boundary!
   457 000003F6 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   458                                  	; eax = 0
   459 000003F8 290D[A0700000]          	sub	[free_pages], ecx ; 07/11/2014
   460                                  mi_8:
   461 000003FE 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   462                                  	;dec	bl
   463 00000401 FEC9                    	dec	cl
   464 00000403 7404                    	jz	short mi_9
   465 00000405 FEC0                    	inc	al
   466 00000407 EBF5                    	jmp	short mi_8
   467                                  mi_9:
   468                                  	;
   469                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   470                                  	;		(allocate pages for system page tables)
   471                                  
   472                                  	; edx = MEM_ALLOC_TBL
   473 00000409 8B0D[9C700000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   474 0000040F 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   475 00000415 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   476                                  				 ; page table count (PDE count)
   477                                  	;
   478 00000418 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   479                                  	;
   480 00000419 41                      	inc	ecx		 ; +1 for kernel page directory	
   481                                  	;
   482 0000041A 290D[A0700000]          	sub	[free_pages], ecx ; 07/11/2014
   483                                  	;
   484 00000420 8B35[98700000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   485 00000426 C1EE0C                  	shr	esi, 12		 ; convert to page number
   486                                  mi_10:
   487 00000429 89F0                    	mov	eax, esi	 ; allocation bit offset
   488 0000042B 89C3                    	mov	ebx, eax
   489 0000042D C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   490 00000430 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   491                                  				 ;   to align on dword boundary
   492 00000433 83E01F                  	and	eax, 31		 ; set allocation bit position 
   493                                  				 ;  (bit 0 to bit 31)
   494                                  	;
   495 00000436 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   496                                  	;
   497 00000438 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   498                                  	;
   499 0000043B 46                      	inc	esi		 ; next page table
   500 0000043C E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   501                                  				 ; (ecx = page table count + 1)
   502                                  	;
   503 0000043E 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   504                                  	;
   505                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   506                                  	;
   507                                  	; Initialize Kernel's Page Directory
   508 0000043F 8B3D[98700000]          	mov	edi, [k_page_dir]
   509 00000445 89F8                    	mov	eax, edi
   510 00000447 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   511                                  		     	      ; supervisor + read&write + present
   512 00000449 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   513                                  mi_11:
   514 0000044B 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   515                                  			        ; EAX points to next page table
   516 00000450 AB                      	stosd
   517 00000451 E2F8                    	loop	mi_11
   518 00000453 29C0                    	sub	eax, eax	; Empty PDE
   519                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   520                                  	; 02/01/2022
   521 00000455 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   522 00000457 29D1                    	sub	ecx, edx
   523 00000459 7402                    	jz	short mi_12
   524 0000045B F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   525                                  	;
   526                                  	; Initialization of Kernel's Page Directory is OK, here.
   527                                  mi_12:
   528                                  	; Initialize Kernel's Page Tables
   529                                  	;
   530                                  	; (EDI points to address of page table 0)
   531                                  	; eax = 0
   532 0000045D 8B0D[9C700000]          	mov	ecx, [memory_size] ; memory size in pages
   533 00000463 89CA                    	mov	edx, ecx	; (***)
   534 00000465 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   535                                  			     ; supervisor + read&write + present
   536                                  mi_13:
   537 00000467 AB                      	stosd
   538 00000468 0500100000              	add	eax, 4096	
   539 0000046D E2F8                    	loop	mi_13
   540                                  	; 02/01/2022
   541 0000046F 66B9FF03                	mov	cx, 1023
   542 00000473 21CA                    	and	edx, ecx
   543                                  	;and	dx, 1023	; (***)
   544 00000475 7407                    	jz	short mi_14
   545                                  	;mov	cx, 1024	
   546                                  	; 02/01/2022
   547                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   548 00000477 41                      	inc	ecx ; ecx = 1024
   549 00000478 29D1                    	sub	ecx, edx
   550                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   551 0000047A 31C0                    	xor	eax, eax
   552 0000047C F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   553                                  				; of the last page table
   554                                  mi_14:
   555                                  	;  Initialization of Kernel's Page Tables is OK, here.
   556                                  	;
   557 0000047E 89F8                    	mov	eax, edi	; end of the last page table page
   558                                  			        ; (beginging of user space pages)
   559 00000480 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   560 00000483 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   561                                  				; aligning on dword boundary
   562                                  	 
   563 00000485 A3[AC700000]            	mov	[first_page], eax
   564 0000048A A3[A4700000]            	mov	[next_page], eax ; The first free page pointer
   565                                  				 ; for user programs
   566                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   567                                  	;
   568                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   569                                  	;
   570                                  	
   571                                  	; Enable paging
   572                                  	;
   573 0000048F A1[98700000]                    mov     eax, [k_page_dir]
   574 00000494 0F22D8                  	mov	cr3, eax
   575 00000497 0F20C0                  	mov	eax, cr0
   576 0000049A 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   577 0000049F 0F22C0                  	mov	cr0, eax
   578                                          ;jmp    KCODE:StartPMP
   579                                  
   580 000004A2 EA                      	db 0EAh 		; Opcode for far jump
   581 000004A3 [A9040000]                      dd StartPMP		; 32 bit offset
   582 000004A7 0800                    	dw KCODE		; kernel code segment descriptor
   583                                  
   584                                  StartPMP:
   585                                  	; 06/11//2014
   586                                  	; Clear video page 0
   587                                  	;
   588                                  	; Temporary Code
   589                                  	;
   590                                  	;mov	ecx, 80*25/2
   591 000004A9 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   592 000004AD BF00800B00              	mov	edi, 0B8000h
   593 000004B2 57                      	push	edi ; * ; 02/01/2022
   594 000004B3 31C0                    	xor	eax, eax	; black background, black fore color
   595 000004B5 F3AB                    	rep	stosd
   596                                  	
   597                                  	; 19/08/2014
   598                                  	; Kernel Base Address = 0
   599                                  	; It is mapped to (physically) 0 in the page table.
   600                                  	; So, here is exactly 'StartPMP' address.
   601                                  	;
   602                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   603                                  	;;mov	esi, msgPM
   604                                  	;; 14/08/2015 (kernel version message will appear
   605                                  	;;	       when protected mode and paging is enabled)
   606 000004B7 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   607 000004B9 BE[F06B0000]            	mov	esi, msgKVER
   608 000004BE 5F                      	pop	edi ; * ; 02/01/2022
   609                                  	;mov	edi, 0B8000h ; 27/08/2014
   610                                  	; 20/08/2014
   611 000004BF E890010000              	call	printk
   612                                  
   613                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   614                                  	; // Set IRQ offsets
   615                                  	;
   616                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   617                                  	;
   618                                  					;; ICW1
   619 000004C4 B011                    	mov	al, 11h			; Initialization sequence
   620 000004C6 E620                    	out	20h, al			; 	8259A-1
   621                                  	; jmp 	$+2
   622 000004C8 E6A0                    	out	0A0h, al		; 	8259A-2
   623                                  					;; ICW2
   624 000004CA B020                    	mov	al, 20h			; Start of hardware ints (20h)
   625 000004CC E621                    	out	21h, al			;	for 8259A-1
   626                                  	; jmp 	$+2
   627 000004CE B028                    	mov	al, 28h			; Start of hardware ints (28h)
   628 000004D0 E6A1                    	out	0A1h, al		; 	for 8259A-2
   629                                  					;
   630 000004D2 B004                    	mov	al, 04h			;; ICW3
   631 000004D4 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   632                                  	; jmp 	$+2
   633 000004D6 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   634 000004D8 E6A1                    	out	0A1h, al		;
   635                                  					;; ICW4
   636 000004DA B001                    	mov	al, 01h	 		;
   637 000004DC E621                    	out	21h, al			; 	8086 mode, normal EOI	
   638                                  	; jmp 	$+2
   639 000004DE E6A1                    	out	0A1h, al		;	for both chips.
   640                                  
   641                                  	;mov	al, 0FFh	; mask off all interrupts for now
   642                                  	;out	21h, al
   643                                  	;; jmp 	$+2
   644                                  	;out	0A1h, al
   645                                  
   646                                  	; 02/04/2015
   647                                  	; 26/03/2015 System call (INT 30h) modification
   648                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   649                                  	;
   650                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   651                                  	;  setup_idt:
   652                                  	;
   653                                          ;; 16/02/2015
   654                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   655                                  	; 21/08/2014 (timer_int)
   656 000004E0 BE[BC680000]            	mov	esi, ilist
   657 000004E5 8D3D[306E0000]          	lea	edi, [idt]
   658                                  	; 26/03/2015
   659                                  	;mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   660                                  	; 02/01/2022
   661 000004EB B130                    	mov	cl, 48 ; ecx = 48
   662                                  	; 02/04/2015
   663 000004ED BB00000800              	mov	ebx, 80000h
   664                                  rp_sidt1:
   665 000004F2 AD                      	lodsd
   666 000004F3 89C2                    	mov	edx, eax
   667 000004F5 66BA008E                	mov	dx, 8E00h
   668 000004F9 6689C3                  	mov	bx, ax
   669 000004FC 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   670                                         			        ; /* interrupt gate - dpl=0, present */
   671 000004FE AB                      	stosd	; selector & offset bits 0-15 	
   672 000004FF 89D0                    	mov	eax, edx
   673 00000501 AB                      	stosd	; attributes & offset bits 16-23
   674 00000502 E2EE                    	loop	rp_sidt1
   675 00000504 B110                    	mov	cl, 16		; 16 software interrupts (INT 30h to INT 3Fh)
   676                                  rp_sidt2:
   677 00000506 AD                      	lodsd
   678 00000507 21C0                    	and	eax, eax
   679 00000509 7413                    	jz	short rp_sidt3
   680 0000050B 89C2                    	mov	edx, eax
   681 0000050D 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   682 00000511 6689C3                  	mov	bx, ax
   683 00000514 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   684 00000516 AB                      	stosd
   685 00000517 89D0                    	mov	eax, edx
   686 00000519 AB                      	stosd
   687 0000051A E2EA                    	loop	rp_sidt2
   688 0000051C EB16                    	jmp	short sidt_OK
   689                                  rp_sidt3:
   690 0000051E B8[78090000]            	mov	eax, ignore_int
   691 00000523 89C2                    	mov	edx, eax
   692 00000525 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   693 00000529 6689C3                  	mov	bx, ax
   694 0000052C 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   695                                  rp_sidt4:
   696 0000052E AB                      	stosd
   697 0000052F 92                      	xchg	eax, edx
   698 00000530 AB                      	stosd
   699 00000531 92                      	xchg	edx, eax
   700 00000532 E2FA                    	loop	rp_sidt4
   701                                  sidt_OK: 
   702 00000534 0F011D[B6680000]        	lidt 	[idtd]
   703                                  	;
   704                                  	; TSS descriptor setup ; 24/03/2015
   705 0000053B B8[30700000]            	mov	eax, task_state_segment
   706 00000540 66A3[AA680000]          	mov	[gdt_tss0], ax
   707 00000546 C1C010                  	rol	eax, 16
   708 00000549 A2[AC680000]            	mov	[gdt_tss1], al
   709 0000054E 8825[AF680000]          	mov	[gdt_tss2], ah
   710 00000554 66C705[96700000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   710 0000055C 00                 
   711                                  		; 
   712                                  		; IO Map Base address (When this address points
   713                                  		; to end of the TSS, CPU does not use IO port 
   714                                  		; permission bit map for RING 3 IO permissions, 
   715                                  		; access to any IO ports in ring 3 will be forbidden.)
   716                                   		;
   717                                  	;mov	[tss.esp0], esp ; TSS offset 4
   718                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   719 0000055D 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   720                                  			 ; occurs (or a system call -software INT- is requested)
   721                                  			 ; while cpu running in ring 3 (in user mode).				
   722                                  			 ; (Kernel stack pointer and segment will be loaded
   723                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   724 00000561 0F00D8                  	ltr	ax  ; Load task register
   725                                  	;
   726                                  esp0_set0:
   727                                  	; 30/07/2015
   728 00000564 8B0D[9C700000]          	mov 	ecx, [memory_size] ; memory size in pages
   729 0000056A C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   730 0000056D 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   731                                  			  ; (kernel mode virtual address)
   732 00000573 7605                    	jna	short esp0_set1
   733                                  	;
   734                                  	; If available memory > CORE (end of the 1st 4 MB)
   735                                  	; set stack pointer to CORE
   736                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   737                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   738 00000575 B900004000              	mov	ecx, CORE
   739                                  esp0_set1:
   740 0000057A 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   741                                  esp0_set_ok:
   742                                  	; 30/07/2015 (**tss.esp0**) 
   743 0000057C 8925[34700000]          	mov	[tss.esp0], esp
   744 00000582 66C705[38700000]10-             mov     word [tss.ss0], KDATA
   744 0000058A 00                 
   745                                  	; 14/08/2015
   746                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   747                                  	;
   748                                  	;cli	; Disable interrupts (for CPU)
   749                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   750                                  	;
   751 0000058B 30C0                    	xor	al, al		; Enable all hardware interrupts!
   752 0000058D E621                    	out	21h, al		; (IBM PC-AT compatibility)
   753 0000058F EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   754 00000591 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   755                                  				; (Even if related hardware component
   756                                  				;  does not exist!)
   757                                  	; Enable NMI 
   758 00000593 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   759 00000595 E670                    	out  	70h, al
   760                                  	; 23/02/2015
   761 00000597 90                      	nop
   762 00000598 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   763                                  				; for preventing unknown state (!?)
   764                                  	;
   765                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   766                                  	;
   767                                  	; 02/09/2014
   768 0000059A 6631DB                  	xor	bx, bx
   769 0000059D 66BA0002                	mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   770 000005A1 E8280F0000              	call	set_cpos
   771                                  	;
   772                                  	; 06/11/2014
   773                                  	; Temporary Code
   774                                  	;
   775 000005A6 E8A1100000              	call	memory_info
   776                                  	; 14/08/2015
   777                                  	;call	getch ; 28/02/2015
   778                                  drv_init:
   779 000005AB FB                      	sti	; Enable Interrupts 
   780                                  	; 06/02/2015
   781 000005AC 8B15[906B0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   782 000005B2 668B1D[8E6B0000]        	mov	bx, [fd0_type] ; fd0, fd1
   783                                  	; 22/02/2015
   784 000005B9 6621DB                  	and	bx, bx
   785 000005BC 751B                    	jnz	short di1
   786                                  	;
   787 000005BE 09D2                    	or 	edx, edx
   788 000005C0 7529                    	jnz	short di2
   789                                  	;
   790                                  setup_error:
   791 000005C2 BE[D96C0000]            	mov 	esi, setup_error_msg
   792                                  psem:	
   793 000005C7 AC                      	lodsb
   794 000005C8 08C0                    	or	al, al
   795                                  	;jz	short haltx ; 22/02/2015
   796 000005CA 7426                    	jz	short di3
   797 000005CC 56                      	push	esi
   798 000005CD 31DB                    	xor	ebx, ebx ; 0
   799                                  			; Video page 0 (bl=0)
   800 000005CF B407                    	mov	ah, 07h ; Black background, 
   801                                  			; light gray forecolor
   802 000005D1 E8EE0D0000              	call	write_tty
   803 000005D6 5E                      	pop	esi
   804 000005D7 EBEE                    	jmp	short psem
   805                                  
   806                                  di1:
   807                                  	; supress 'jmp short T6'
   808                                  	;  (activate fdc motor control code)
   809 000005D9 66C705[D5060000]90-     	mov	word [T5], 9090h ; nop
   809 000005E1 90                 
   810                                  	;
   811                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   812                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   813                                  	;stosw
   814                                  	;mov 	ax, cs
   815                                  	;stosw
   816                                  	;; 16/02/2015
   817                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   818                                  	;
   819 000005E2 E8761F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   820                                  	;
   821 000005E7 09D2                    	or	edx, edx
   822 000005E9 7407                            jz      short di3
   823                                  di2:
   824 000005EB E8B21F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   825 000005F0 72D0                            jc      short setup_error
   826                                  di3:
   827 000005F2 E829100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   828                                  	;
   829 000005F7 E8D9610000              	call	display_disks ; 07/03/2015  (Temporary)
   830                                  ;haltx:
   831                                  	; 14/08/2015
   832                                  	;call	getch ; 22/02/2015
   833 000005FC FB                      	sti	; Enable interrupts (for CPU)
   834                                  	; 14/08/2015
   835                                  	;mov 	ecx, 0FFFFFFFh
   836                                  	; 22/11/2021
   837 000005FD B9FFFF2F00              	mov 	ecx, 02FFFFFh
   838                                  md_info_msg_wait:
   839 00000602 51                      	push 	ecx
   840 00000603 B001                    	mov	al, 1
   841 00000605 8A25[C6700000]          	mov 	ah, [ptty] ; active (current) video page
   842 0000060B E80E5F0000              	call	getc_n
   843 00000610 59                      	pop	ecx
   844 00000611 7502                    	jnz	short md_info_msg_ok
   845 00000613 E2ED                    	loop	md_info_msg_wait
   846                                  md_info_msg_ok:
   847                                  	; 30/06/2015
   848 00000615 E8932C0000              	call	sys_init
   849                                  	;
   850                                  	;jmp 	cpu_reset ; 22/02/2015
   851                                  hang:
   852                                  	; 04/12/2021
   853 0000061A 29C0                    	sub	eax, eax
   854                                  _hang:	
   855                                  	; 23/02/2015
   856                                  	;sti			; Enable interrupts
   857 0000061C F4                      	hlt
   858                                  	;
   859                                  	;nop
   860                                  	;; 03/12/2014
   861                                  	;; 28/08/2014
   862                                  	;mov	ah, 11h
   863                                  	;call	getc
   864                                  	;jz     _c8
   865                                  	;
   866                                  	; 23/02/2015
   867                                  	; 06/02/2015
   868                                  	; 07/09/2014
   869 0000061D 31DB                    	xor	ebx, ebx
   870 0000061F 8A1D[C6700000]          	mov	bl, [ptty]	; active_page
   871 00000625 89DE                    	mov	esi, ebx
   872 00000627 66D1E6                  	shl 	si, 1
   873 0000062A 81C6[C8700000]          	add	esi, ttychr
   874 00000630 668B06                  	mov	ax, [esi]
   875                                  	;and	ax, ax
   876                                  	;;jz	short _c8
   877                                  	;jz	short hang
   878                                  	; 04/12/2021
   879 00000633 21C0                    	and	eax, eax
   880 00000635 74E5                    	jz	short _hang
   881 00000637 66C7060000              	mov	word [esi], 0
   882 0000063C 80FB03                  	cmp	bl, 3		; Video page 3
   883                                  	;jb	short _c8
   884 0000063F 72D9                    	jb	short hang
   885                                  	;	
   886                                  	; 02/09/2014
   887 00000641 B40E                    	mov	ah, 0Eh		; Yellow character 
   888                                  				; on black background
   889                                  	; 30/11/2021 (32 bit reg push-pop)
   890                                  	; 07/09/2014
   891                                  nxtl:
   892 00000643 53                      	push	ebx
   893                                  	;
   894                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   895                                  				; bh = 0 (video mode)
   896                                  				; Retro UNIX 386 v1 - Video Mode 0
   897                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   898 00000644 50                      	push	eax
   899 00000645 E87A0D0000              	call 	write_tty
   900 0000064A 58                      	pop	eax
   901                                  	;pop	bx
   902 0000064B 5B                      	pop	ebx
   903 0000064C 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   904                                  	;jne	short _c8
   905 0000064E 75CA                    	jne	short hang
   906 00000650 B00A                    	mov	al, 0Ah		; next line
   907 00000652 EBEF                    	jmp	short nxtl
   908                                  	
   909                                  ;_c8:
   910                                  ;	; 25/08/2014
   911                                  ;	cli			; Disable interrupts
   912                                  ;	mov	al, [scounter + 1]
   913                                  ;	and	al, al
   914                                  ;	jnz	hang
   915                                  ;	call	rtc_p
   916                                  ;	jmp     hang
   917                                  
   918                                  
   919                                  	; 27/08/2014
   920                                  	; 20/08/2014
   921                                  printk:
   922                                          ;mov    edi, [scr_row]
   923                                  pkl:
   924 00000654 AC                      	lodsb
   925 00000655 08C0                    	or 	al, al
   926 00000657 7404                    	jz	short pkr
   927 00000659 66AB                    	stosw
   928 0000065B EBF7                    	jmp	short pkl
   929                                  pkr:
   930 0000065D C3                      	retn
   931                                  
   932                                  ; 25/07/2015
   933                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   934                                  ; 17/02/2015
   935                                  ; 06/02/2015 (unix386.s)
   936                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   937                                  ;
   938                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   939                                  ;
   940                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   941                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   942                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   943                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   944                                  ;									       :
   945                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   946                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   947                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   948                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   949                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   950                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   951                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   952                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   953                                  ;-------------------------------------------------------------------------------
   954                                  ;
   955                                  
   956                                  timer_int:	; IRQ 0
   957                                  ;int_08h:	; Timer
   958                                  	; 14/10/2015
   959                                  	; Here, we are simulating system call entry (for task switch)
   960                                  	; (If multitasking is enabled, 
   961                                  	; 'clock' procedure may jump to 'sysrelease')
   962 0000065E 1E                      	push	ds
   963 0000065F 06                      	push	es
   964 00000660 0FA0                    	push	fs
   965 00000662 0FA8                    	push	gs
   966 00000664 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   967 00000665 66B91000                	mov     cx, KDATA
   968 00000669 8ED9                            mov     ds, cx
   969 0000066B 8EC1                            mov     es, cx
   970 0000066D 8EE1                            mov     fs, cx
   971 0000066F 8EE9                            mov     gs, cx
   972                                  	;
   973 00000671 0F20D9                  	mov	ecx, cr3
   974 00000674 890D[17070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   975                                  	;
   976 0000067A 3B0D[98700000]          	cmp 	ecx, [k_page_dir]
   977 00000680 741F                    	je	short T3
   978                                  	;
   979                                  	; timer interrupt has been occurred while OS is in user mode
   980 00000682 A3[AC750000]            	mov 	[u.r0], eax
   981 00000687 89E1                    	mov	ecx, esp
   982 00000689 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   983 0000068C 890D[A4750000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   984 00000692 8925[A8750000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   985                                  	;
   986 00000698 8B0D[98700000]          	mov	ecx, [k_page_dir]
   987 0000069E 0F22D9                  	mov	cr3, ecx
   988                                  T3:
   989 000006A1 FB                      	sti				; INTERRUPTS BACK ON
   990 000006A2 66FF05[14710000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   991 000006A9 7507                    	JNZ	short T4		; GO TO TEST_DAY
   992 000006AB 66FF05[16710000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   993                                  T4:					; TEST_DAY
   994 000006B2 66833D[16710000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   995 000006BA 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   996 000006BC 66813D[14710000]B0-     	CMP	word [TIMER_LOW],0B0H
   996 000006C4 00                 
   997 000006C5 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   998                                  
   999                                  ;-----	TIMER HAS GONE 24 HOURS
  1000                                  	;;SUB	AX,AX
  1001                                  	;MOV	[TIMER_HIGH],AX
  1002                                  	;MOV	[TIMER_LOW],AX
  1003 000006C7 29C0                    	sub	eax, eax
  1004 000006C9 A3[14710000]            	mov	[TIMER_LH], eax
  1005                                  	;	
  1006 000006CE C605[18710000]01        	MOV	byte [TIMER_OFL],1
  1007                                  
  1008                                  ;-----	TEST FOR DISKETTE TIME OUT
  1009                                  
  1010                                  T5:
  1011                                  	; 23/12/2014
  1012 000006D5 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1013                                  					; (9090h) if a floppy disk
  1014                                  					; is detected.
  1015                                  	;mov	al,[CS:MOTOR_COUNT]
  1016 000006D7 A0[1B710000]            	mov	al, [MOTOR_COUNT]
  1017 000006DC FEC8                    	dec	al
  1018                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1019 000006DE A2[1B710000]            	mov	[MOTOR_COUNT], al
  1020                                  	;mov	[ORG_MOTOR_COUNT], al
  1021 000006E3 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1022 000006E5 B0F0                    	mov 	al,0F0h
  1023                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1024 000006E7 2005[1A710000]          	and	[MOTOR_STATUS], al
  1025                                  	;and	[ORG_MOTOR_STATUS], al
  1026 000006ED B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1027                                  					; bit 2 = enable controller
  1028                                  					;	1 = normal operation
  1029                                  					;	0 = reset	
  1030                                  					; bit 0, 1 = drive select
  1031                                  					; bit 4-7 = motor running bits 
  1032 000006EF 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1033 000006F3 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1034                                  T6:	
  1035                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1036                                  					; TIMER TICK INTERRUPT
  1037                                  	;;inc	word [wait_count] ;;27/02/2015
  1038                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1039                                  	;;;;cli
  1040                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1041 000006F4 FF15[0F070000]          	call	[x_timer] ; 14/05/2015
  1042                                  T7:
  1043                                  	; 14/10/2015
  1044 000006FA B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1045 000006FC FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1046 000006FD E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1047                                  	;
  1048 000006FF A1[17070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1049 00000704 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1050                                  	;
  1051 00000707 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1052                                  	;
  1053 00000708 0FA9                    	pop	gs
  1054 0000070A 0FA1                    	pop	fs
  1055 0000070C 07                      	pop	es
  1056 0000070D 1F                      	pop	ds
  1057 0000070E CF                      	iretd	; return from interrupt
  1058                                  
  1059                                  
  1060                                  ; ////////////////
  1061                                  
  1062                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1063                                  x_timer:
  1064 0000070F [1B070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1065                                  	;dd	clock
  1066                                  
  1067                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1068                                  x_rtci:
  1069 00000713 [510A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1070                                  
  1071                                  ; 14/10/2015
  1072 00000717 00000000                cr3reg: dd 0
  1073                                  
  1074                                  	; 04/12/2021 - Retro UNIX 386 v1.2
  1075                                  	; 06/02/2015
  1076                                  	; 07/09/2014
  1077                                  	; 21/08/2014
  1078                                  u_timer:
  1079                                  ;timer_int:	; IRQ 0
  1080                                  	; 06/02/2015
  1081                                  	;push	eax
  1082                                  	;push	edx
  1083                                  	;push	ecx
  1084                                  	;push	ebx
  1085                                  	;push	ds
  1086                                  	;push	es
  1087                                  	;mov	eax, KDATA
  1088                                  	;mov	ds, ax
  1089                                  	;mov	es, ax
  1090 0000071B FF05[DC700000]          	inc	dword [tcount]
  1091 00000721 BB[626C0000]            	mov	ebx, tcountstr + 4
  1092                                  	;mov	ax, [tcount]
  1093                                  	; 04/12/2021
  1094 00000726 A1[DC700000]            	mov	eax, [tcount]
  1095 0000072B B90A000000              	mov	ecx, 10
  1096                                  rp_divtcnt:
  1097 00000730 31D2                    	xor	edx, edx
  1098 00000732 F7F1                    	div	ecx
  1099 00000734 80C230                  	add	dl, 30h
  1100 00000737 8813                    	mov	[ebx], dl
  1101                                  	;or	ax, ax
  1102                                  	; 04/12/2021
  1103 00000739 09C0                    	or	eax, eax
  1104 0000073B 7403                    	jz	short print_lzero
  1105 0000073D 4B                      	dec	ebx
  1106 0000073E EBF0                    	jmp	short rp_divtcnt
  1107                                  print_lzero:
  1108 00000740 81FB[5E6C0000]          	cmp	ebx, tcountstr
  1109 00000746 7606                    	jna	short print_tcount
  1110 00000748 4B                      	dec	ebx
  1111 00000749 C60330                   	mov	byte [ebx], 30h
  1112 0000074C EBF2                    	jmp	short print_lzero
  1113                                  print_tcount:
  1114 0000074E 56                      	push	esi
  1115 0000074F 57                      	push	edi
  1116 00000750 BE[3A6C0000]            	mov	esi, timer_msg ; Timer interrupt message
  1117                                  	; 07/09/2014
  1118                                  	;mov	bx, 1	; Video page 1
  1119                                  	; 04/12/2021
  1120 00000755 29DB                    	sub	ebx, ebx
  1121                                  	;inc	bl ; ebx = 1
  1122                                  	; 02/01/2022
  1123 00000757 B306                    	mov	bl, 6	; Video page 6
  1124                                  ptmsg:
  1125 00000759 AC                      	lodsb
  1126 0000075A 08C0                    	or	al, al
  1127 0000075C 740D                    	jz	short ptmsg_ok
  1128 0000075E 56                      	push	esi
  1129                                  	;push	bx
  1130                                  	; 04/12/2021
  1131 0000075F 53                              push	ebx
  1132 00000760 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1133 00000762 E85D0C0000              	call 	write_tty
  1134                                  	;pop	bx
  1135                                  	; 04/12/2021
  1136 00000767 5B                      	pop	ebx
  1137 00000768 5E                      	pop	esi
  1138 00000769 EBEE                    	jmp	short ptmsg
  1139                                  	;; 27/08/2014
  1140                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1141                                  	;call	printk
  1142                                  	;
  1143                                  ptmsg_ok:
  1144                                  	; 07/09/2014
  1145                                  	;xor	dx, dx		; column 0, row 0
  1146                                  	; 04/12/2021
  1147 0000076B 31D2                    	xor	edx, edx
  1148 0000076D E85C0D0000              	call	set_cpos	; set cursor position to 0,0 
  1149                                  	; 23/02/2015
  1150                                  	; 25/08/2014
  1151                                  	;mov	ebx, scounter		; (seconds counter)
  1152                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1153                                  ;	dec	byte [scounter+1]
  1154                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1155                                  ;	jns	short u_timer_retn
  1156                                  	; 26/02/2015
  1157                                  ;	call	rtc_p
  1158                                  ;	mov	ebx, scounter		; (seconds counter)
  1159                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1160                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1161                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1162                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1163                                  ;	mov	byte [ebx], 5
  1164                                  ;	inc	byte [ebx+1] ; 19
  1165                                  ;;timer_eoi:
  1166                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1167                                  ;;	out	20h, al	; 8259 PORT
  1168                                  	;
  1169                                  ;u_timer_retn:  ; 06/02/2015
  1170 00000772 5F                      	pop	edi
  1171 00000773 5E                      	pop	esi
  1172                                  	;pop	es
  1173                                  	;pop	ds
  1174                                  	;pop	ebx
  1175                                  	;pop	ecx
  1176                                  	;pop	edx
  1177                                  	;pop	eax
  1178                                  	;iret
  1179 00000774 C3                      	retn	; 06/02/2015
  1180                                  
  1181                                  	; 28/08/2014
  1182                                  irq0:
  1183 00000775 6A00                            push 	dword 0
  1184 00000777 EB48                    	jmp	short which_irq
  1185                                  irq1:
  1186 00000779 6A01                            push 	dword 1
  1187 0000077B EB44                    	jmp	short which_irq
  1188                                  irq2:
  1189 0000077D 6A02                            push 	dword 2
  1190 0000077F EB40                    	jmp	short which_irq
  1191                                  irq3:
  1192                                  	; 20/11/2015
  1193                                  	; 24/10/2015
  1194 00000781 2EFF15[3F3A0000]        	call	dword [cs:com2_irq3]
  1195 00000788 6A03                    	push 	dword 3
  1196 0000078A EB35                    	jmp	short which_irq
  1197                                  irq4:
  1198                                  	; 20/11/2015
  1199                                  	; 24/10/2015
  1200 0000078C 2EFF15[3B3A0000]        	call	dword [cs:com1_irq4]
  1201 00000793 6A04                            push 	dword 4
  1202 00000795 EB2A                    	jmp	short which_irq
  1203                                  irq5:
  1204 00000797 6A05                            push 	dword 5
  1205 00000799 EB26                    	jmp	short which_irq
  1206                                  irq6:
  1207 0000079B 6A06                            push 	dword 6
  1208 0000079D EB22                    	jmp	short which_irq
  1209                                  irq7:
  1210 0000079F 6A07                            push 	dword 7
  1211 000007A1 EB1E                    	jmp	short which_irq
  1212                                  irq8:
  1213 000007A3 6A08                            push 	dword 8
  1214 000007A5 EB1A                    	jmp	short which_irq
  1215                                  irq9:
  1216 000007A7 6A09                            push 	dword 9
  1217 000007A9 EB16                    	jmp	short which_irq
  1218                                  irq10:
  1219 000007AB 6A0A                            push 	dword 10
  1220 000007AD EB12                    	jmp	short which_irq
  1221                                  irq11:
  1222 000007AF 6A0B                            push 	dword 11
  1223 000007B1 EB0E                    	jmp	short which_irq
  1224                                  irq12:
  1225 000007B3 6A0C                            push 	dword 12
  1226 000007B5 EB0A                    	jmp	short which_irq
  1227                                  irq13:
  1228 000007B7 6A0D                            push 	dword 13
  1229 000007B9 EB06                    	jmp	short which_irq
  1230                                  irq14:
  1231 000007BB 6A0E                            push 	dword 14
  1232 000007BD EB02                    	jmp	short which_irq
  1233                                  irq15:
  1234 000007BF 6A0F                            push 	dword 15
  1235                                  	;jmp	short which_irq
  1236                                  
  1237                                  	; 19/10/2015
  1238                                  	; 29/08/2014
  1239                                  	; 21/08/2014
  1240                                  which_irq:
  1241 000007C1 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1242 000007C4 53                      	push	ebx
  1243 000007C5 56                      	push	esi
  1244 000007C6 57                      	push	edi
  1245 000007C7 1E                      	push 	ds
  1246 000007C8 06                      	push 	es
  1247                                  	;
  1248 000007C9 88C3                    	mov	bl, al
  1249                                  	;
  1250 000007CB B810000000              	mov	eax, KDATA
  1251 000007D0 8ED8                    	mov	ds, ax
  1252 000007D2 8EC0                    	mov	es, ax
  1253                                  	; 19/10/2015
  1254 000007D4 FC                      	cld
  1255                                          ; 27/08/2014
  1256 000007D5 8105[E86B0000]A000-             add     dword [scr_row], 0A0h
  1256 000007DD 0000               
  1257                                  	;
  1258 000007DF B417                    	mov	ah, 17h	; blue (1) background, 
  1259                                  			; light gray (7) forecolor
  1260 000007E1 8B3D[E86B0000]                  mov     edi, [scr_row]
  1261 000007E7 B049                    	mov	al, 'I'
  1262 000007E9 66AB                    	stosw
  1263 000007EB B052                    	mov	al, 'R'
  1264 000007ED 66AB                    	stosw
  1265 000007EF B051                    	mov	al, 'Q'
  1266 000007F1 66AB                    	stosw
  1267 000007F3 B020                    	mov	al, ' '
  1268 000007F5 66AB                    	stosw
  1269 000007F7 88D8                    	mov	al, bl
  1270 000007F9 3C0A                    	cmp	al, 10
  1271 000007FB 7208                    	jb	short iix
  1272 000007FD B031                    	mov	al, '1'
  1273 000007FF 66AB                    	stosw
  1274 00000801 88D8                    	mov	al, bl
  1275 00000803 2C0A                    	sub	al, 10
  1276                                  iix:
  1277 00000805 0430                    	add	al, '0'
  1278 00000807 66AB                    	stosw
  1279 00000809 B020                    	mov	al, ' '
  1280 0000080B 66AB                    	stosw
  1281 0000080D B021                    	mov	al, '!'
  1282 0000080F 66AB                    	stosw
  1283 00000811 B020                    	mov	al, ' '
  1284 00000813 66AB                    	stosw
  1285                                  	; 23/02/2015
  1286 00000815 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1287                                  	;jna	iiret
  1288                                  	; 04/12/2021
  1289 00000818 7604                    	jna	short iiz
  1290                                  iiy:
  1291 0000081A B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1292 0000081C E6A0                    	out	0A0h, al ; the 2nd 8259
  1293                                  iiz:
  1294 0000081E E983010000              	jmp     iiret
  1295                                  	;
  1296                                  	; 22/08/2014
  1297                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1298                                  	;out	20h, al	; 8259 PORT
  1299                                  	;
  1300                                  	;pop	es
  1301                                  	;pop	ds
  1302                                  	;pop	edi
  1303                                  	;pop	esi
  1304                                  	;pop	ebx
  1305                                  	;pop 	eax
  1306                                  	;iret
  1307                                  
  1308                                  	; 02/04/2015
  1309                                  	; 25/08/2014
  1310                                  exc0:
  1311 00000823 6A00                            push 	dword 0
  1312 00000825 E990000000                      jmp     cpu_except
  1313                                  exc1:
  1314 0000082A 6A01                            push 	dword 1
  1315 0000082C E989000000                      jmp     cpu_except
  1316                                  exc2:
  1317 00000831 6A02                            push 	dword 2
  1318 00000833 E982000000                      jmp     cpu_except
  1319                                  exc3:
  1320 00000838 6A03                            push 	dword 3
  1321 0000083A EB7E                            jmp     cpu_except
  1322                                  exc4:
  1323 0000083C 6A04                            push 	dword 4
  1324 0000083E EB7A                            jmp     cpu_except
  1325                                  exc5:
  1326 00000840 6A05                            push 	dword 5
  1327 00000842 EB76                            jmp     cpu_except
  1328                                  exc6:
  1329 00000844 6A06                            push 	dword 6
  1330 00000846 EB72                            jmp     cpu_except
  1331                                  exc7:
  1332 00000848 6A07                            push 	dword 7
  1333 0000084A EB6E                            jmp     cpu_except
  1334                                  exc8:
  1335                                  	; [esp] = Error code
  1336 0000084C 6A08                            push 	dword 8
  1337 0000084E EB5C                            jmp     cpu_except_en
  1338                                  exc9:
  1339 00000850 6A09                            push 	dword 9
  1340 00000852 EB66                            jmp     cpu_except
  1341                                  exc10:
  1342                                  	; [esp] = Error code
  1343 00000854 6A0A                            push 	dword 10
  1344 00000856 EB54                            jmp     cpu_except_en
  1345                                  exc11:
  1346                                  	; [esp] = Error code
  1347 00000858 6A0B                            push 	dword 11
  1348 0000085A EB50                            jmp     cpu_except_en
  1349                                  exc12:
  1350                                  	; [esp] = Error code
  1351 0000085C 6A0C                            push 	dword 12
  1352 0000085E EB4C                            jmp     cpu_except_en
  1353                                  exc13:
  1354                                  	; [esp] = Error code
  1355 00000860 6A0D                            push 	dword 13
  1356 00000862 EB48                            jmp     cpu_except_en
  1357                                  exc14:
  1358                                  	; [esp] = Error code
  1359 00000864 6A0E                            push 	dword 14
  1360 00000866 EB44                    	jmp	short cpu_except_en
  1361                                  exc15:
  1362 00000868 6A0F                            push 	dword 15
  1363 0000086A EB4E                            jmp     cpu_except
  1364                                  exc16:
  1365 0000086C 6A10                            push 	dword 16
  1366 0000086E EB4A                            jmp     cpu_except
  1367                                  exc17:
  1368                                  	; [esp] = Error code
  1369 00000870 6A11                            push 	dword 17
  1370 00000872 EB38                    	jmp	short cpu_except_en
  1371                                  exc18:
  1372 00000874 6A12                            push 	dword 18
  1373 00000876 EB42                    	jmp	short cpu_except
  1374                                  exc19:
  1375 00000878 6A13                            push 	dword 19
  1376 0000087A EB3E                    	jmp	short cpu_except
  1377                                  exc20:
  1378 0000087C 6A14                            push 	dword 20
  1379 0000087E EB3A                    	jmp	short cpu_except
  1380                                  exc21:
  1381 00000880 6A15                            push 	dword 21
  1382 00000882 EB36                    	jmp	short cpu_except
  1383                                  exc22:
  1384 00000884 6A16                            push 	dword 22
  1385 00000886 EB32                    	jmp	short cpu_except
  1386                                  exc23:
  1387 00000888 6A17                            push 	dword 23
  1388 0000088A EB2E                    	jmp	short cpu_except
  1389                                  exc24:
  1390 0000088C 6A18                            push 	dword 24
  1391 0000088E EB2A                    	jmp	short cpu_except
  1392                                  exc25:
  1393 00000890 6A19                            push 	dword 25
  1394 00000892 EB26                    	jmp	short cpu_except
  1395                                  exc26:
  1396 00000894 6A1A                            push 	dword 26
  1397 00000896 EB22                    	jmp	short cpu_except
  1398                                  exc27:
  1399 00000898 6A1B                            push 	dword 27
  1400 0000089A EB1E                    	jmp	short cpu_except
  1401                                  exc28:
  1402 0000089C 6A1C                            push 	dword 28
  1403 0000089E EB1A                    	jmp	short cpu_except
  1404                                  exc29:
  1405 000008A0 6A1D                            push 	dword 29
  1406 000008A2 EB16                    	jmp	short cpu_except
  1407                                  exc30:
  1408 000008A4 6A1E                            push 	dword 30
  1409 000008A6 EB04                    	jmp	short cpu_except_en
  1410                                  exc31:
  1411 000008A8 6A1F                            push 	dword 31
  1412 000008AA EB0E                            jmp     short cpu_except
  1413                                  
  1414                                  	; 02/01/2022 (Retro UNIX 386 v1.2)
  1415                                  	; 19/10/2015
  1416                                  	; 19/09/2015
  1417                                  	; 01/09/2015
  1418                                  	; 28/08/2015
  1419                                  	; 28/08/2014
  1420                                  cpu_except_en:
  1421 000008AC 87442404                	xchg	eax, [esp+4] ; Error code
  1422 000008B0 36A3[48710000]          	mov	[ss:error_code], eax
  1423 000008B6 58                      	pop	eax  ; Exception number
  1424 000008B7 870424                  	xchg	eax, [esp]
  1425                                  		; eax = eax before exception
  1426                                  		; [esp] -> exception number
  1427                                  		; [esp+4] -> EIP to return
  1428                                  	; 19/10/2015
  1429                                  	; 19/09/2015
  1430                                  	; 01/09/2015
  1431                                  	; 28/08/2015
  1432                                  	; 29/08/2014
  1433                                  	; 28/08/2014
  1434                                  	; 25/08/2014
  1435                                  	; 21/08/2014
  1436                                  cpu_except:	; CPU Exceptions
  1437 000008BA FC                      	cld
  1438 000008BB 870424                  	xchg	eax, [esp] 
  1439                                  		; eax = Exception number
  1440                                  		; [esp] = eax (before exception)
  1441 000008BE 53                      	push	ebx
  1442 000008BF 56                      	push	esi
  1443 000008C0 57                      	push	edi
  1444 000008C1 1E                      	push 	ds
  1445 000008C2 06                      	push 	es
  1446                                  	; 28/08/2015
  1447 000008C3 66BB1000                	mov	bx, KDATA
  1448 000008C7 8EDB                    	mov	ds, bx
  1449 000008C9 8EC3                    	mov	es, bx
  1450 000008CB 0F20DB                  	mov	ebx, cr3
  1451 000008CE 53                      	push	ebx ; (*) page directory
  1452                                  	; 19/10/2015
  1453 000008CF FC                      	cld
  1454                                  	; 25/03/2015
  1455 000008D0 8B1D[98700000]          	mov	ebx, [k_page_dir]
  1456 000008D6 0F22DB                  	mov	cr3, ebx
  1457                                  	; 28/08/2015
  1458 000008D9 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1459 000008DC 7513                    	jne	short cpu_except_nfp
  1460 000008DE E884270000              	call	page_fault_handler
  1461 000008E3 21C0                    	and 	eax, eax
  1462                                  	;jz	iiretp ; 01/09/2015
  1463                                  	; 02/01/2022
  1464 000008E5 7505                    	jnz	short cpu_except_pf
  1465 000008E7 E9B6000000              	jmp	iiretp
  1466                                  cpu_except_pf:
  1467 000008EC B80E000000              	mov	eax, 0Eh ; 14
  1468                                  cpu_except_nfp:
  1469                                  	; 02/04/2015
  1470 000008F1 BB[1A060000]            	mov	ebx, hang
  1471 000008F6 875C241C                	xchg	ebx, [esp+28]
  1472                                  		; EIP (points to instruction which faults)
  1473                                  	  	; New EIP (hang)
  1474 000008FA 891D[4C710000]          	mov	[FaultOffset], ebx
  1475 00000900 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1476 00000908 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1477                                  	;
  1478 00000910 88C4                    	mov	ah, al
  1479 00000912 240F                    	and	al, 0Fh
  1480 00000914 3C09                    	cmp	al, 9
  1481 00000916 7602                    	jna	short h1ok
  1482 00000918 0407                    	add	al, 'A'-':'
  1483                                  h1ok:
  1484 0000091A D0EC                    	shr	ah, 1
  1485 0000091C D0EC                    	shr	ah, 1
  1486 0000091E D0EC                    	shr	ah, 1
  1487 00000920 D0EC                    	shr	ah, 1
  1488 00000922 80FC09                  	cmp	ah, 9
  1489 00000925 7603                    	jna	short h2ok
  1490 00000927 80C407                  	add	ah, 'A'-':'
  1491                                  h2ok:	
  1492 0000092A 86E0                    	xchg 	ah, al	
  1493 0000092C 66053030                	add	ax, '00'
  1494 00000930 66A3[766C0000]          	mov	[excnstr], ax
  1495                                  	;
  1496                                  	; 29/08/2014
  1497 00000936 A1[4C710000]            	mov	eax, [FaultOffset]
  1498 0000093B 51                      	push	ecx
  1499 0000093C 52                      	push	edx
  1500 0000093D 89E3                    	mov	ebx, esp
  1501                                  	; 28/08/2015
  1502 0000093F B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1503                                  			  ; to hexadecimal string
  1504                                  	;mov	ecx, 10	    ; divisor to convert
  1505                                  			    ; binary number to decimal string
  1506                                  b2d1:
  1507 00000944 31D2                    	xor	edx, edx
  1508 00000946 F7F1                    	div	ecx
  1509                                  	;push	dx
  1510                                  	; 02/01/2022
  1511 00000948 52                      	push	edx
  1512 00000949 39C8                    	cmp	eax, ecx
  1513 0000094B 73F7                    	jnb	short b2d1
  1514 0000094D BF[816C0000]            	mov	edi, EIPstr ; EIP value
  1515                                  			    ; points to instruction which faults
  1516                                  	; 28/08/2015
  1517 00000952 89C2                    	mov	edx, eax
  1518                                  b2d2:
  1519                                  	;add	al, '0'
  1520 00000954 8A82[04170000]          	mov	al, [edx+hexchrs]
  1521 0000095A AA                      	stosb		    ; write hexadecimal digit to its place
  1522 0000095B 39E3                    	cmp	ebx, esp
  1523 0000095D 7605                    	jna	short b2d3
  1524                                  	; 02/01/2022
  1525 0000095F 58                      	pop	eax
  1526                                  	;pop	ax
  1527 00000960 88C2                    	mov	dl, al
  1528 00000962 EBF0                    	jmp	short b2d2
  1529                                  b2d3:
  1530 00000964 B068                    	mov 	al, 'h' ; 28/08/2015
  1531 00000966 AA                      	stosb
  1532 00000967 B020                    	mov	al, 20h	    ; space
  1533 00000969 AA                      	stosb
  1534 0000096A 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1535 0000096C AA                      	stosb
  1536                                  	;
  1537 0000096D 5A                      	pop	edx
  1538 0000096E 59                      	pop	ecx
  1539                                  	;
  1540 0000096F B44F                    	mov	ah, 4Fh	; red (4) background, 
  1541                                  			; white (F) forecolor
  1542 00000971 BE[666C0000]            	mov	esi, exc_msg ; message offset
  1543                                  	;
  1544 00000976 EB11                    	jmp	short piemsg
  1545                                  	;
  1546                                          ;add    dword [scr_row], 0A0h
  1547                                          ;mov    edi, [scr_row]
  1548                                          ;
  1549                                  	;call 	printk
  1550                                  	;
  1551                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1552                                  	;out	20h, al	; 8259 PORT
  1553                                  	;
  1554                                  	;pop	es
  1555                                  	;pop	ds
  1556                                  	;pop	edi
  1557                                  	;pop	esi
  1558                                  	;pop 	eax
  1559                                  	;iret
  1560                                  	
  1561                                  	; 28/08/2015
  1562                                  	; 23/02/2015
  1563                                  	; 20/08/2014
  1564                                  ignore_int:
  1565 00000978 50                      	push	eax
  1566 00000979 53                      	push	ebx ; 23/02/2015
  1567 0000097A 56                      	push	esi
  1568 0000097B 57                      	push	edi
  1569 0000097C 1E                      	push 	ds
  1570 0000097D 06                      	push 	es
  1571                                  	; 28/08/2015
  1572 0000097E 0F20D8                  	mov	eax, cr3
  1573 00000981 50                      	push	eax ; (*) page directory
  1574                                  	;
  1575 00000982 B467                    	mov	ah, 67h	; brown (6) background, 
  1576                                  			; light gray (7) forecolor
  1577 00000984 BE[246C0000]            	mov	esi, int_msg ; message offset
  1578                                  piemsg:
  1579                                          ; 27/08/2014
  1580 00000989 8105[E86B0000]A000-             add     dword [scr_row], 0A0h
  1580 00000991 0000               
  1581 00000993 8B3D[E86B0000]                  mov     edi, [scr_row]
  1582                                          ;
  1583 00000999 E8B6FCFFFF              	call 	printk
  1584                                  	;
  1585                                  	; 23/02/2015
  1586 0000099E B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1587 000009A0 E6A0                    	out	0A0h, al ; the 2nd 8259
  1588                                  iiretp: ; 01/09/2015
  1589                                  	; 28/08/2015
  1590 000009A2 58                      	pop	eax ; (*) page directory
  1591 000009A3 0F22D8                  	mov	cr3, eax
  1592                                  	;
  1593                                  iiret:
  1594                                  	; 22/08/2014
  1595 000009A6 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1596 000009A8 E620                    	out	20h, al	; 8259 PORT
  1597                                  	;
  1598 000009AA 07                      	pop	es
  1599 000009AB 1F                      	pop	ds
  1600 000009AC 5F                      	pop	edi
  1601 000009AD 5E                      	pop	esi
  1602 000009AE 5B                      	pop	ebx ; 29/08/2014
  1603 000009AF 58                      	pop 	eax
  1604 000009B0 CF                      	iretd
  1605                                  
  1606                                  	; 23/02/2022
  1607                                  	; 26/02/2015
  1608                                  	; 07/09/2014
  1609                                  	; 25/08/2014
  1610                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1611                                  	; 22/08/2014
  1612 000009B1 50                      	push	eax
  1613 000009B2 53                      	push	ebx ; 29/08/2014
  1614 000009B3 56                      	push	esi
  1615 000009B4 57                      	push	edi
  1616 000009B5 1E                      	push 	ds
  1617 000009B6 06                      	push 	es
  1618                                  	;
  1619 000009B7 B810000000              	mov	eax, KDATA
  1620 000009BC 8ED8                    	mov	ds, ax
  1621 000009BE 8EC0                    	mov	es, ax
  1622                                  	;
  1623                                  	; 25/08/2014
  1624                                  	;call	rtc_p
  1625                                  	; 23/02/2022
  1626 000009C0 FF15[13070000]          	call	[x_rtci]
  1627                                  	;
  1628                                  	; 22/02/2015 - dsectpm.s
  1629                                  	; [ source: http://wiki.osdev.org/RTC ]
  1630                                  	; read status register C to complete procedure
  1631                                  	;(it is needed to get a next IRQ 8) 
  1632 000009C6 B00C                    	mov	al, 0Ch ; 
  1633 000009C8 E670                    	out	70h, al ; select register C
  1634 000009CA 90                      	nop
  1635 000009CB E471                    	in	al, 71h ; just throw away contents
  1636                                  	; 22/02/2015
  1637 000009CD B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1638 000009CF E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1639                                  	;
  1640 000009D1 EBD3                    	jmp	short iiret	
  1641                                  
  1642                                  	; 22/08/2014
  1643                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1644                                  	; (INT 1Ah)
  1645                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1646                                  time_of_day:
  1647 000009D3 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1648 000009D8 726F                            jc      short rtc_retn 
  1649 000009DA B000                    	mov	al, CMOS_SECONDS
  1650 000009DC E847010000              	call	CMOS_READ
  1651 000009E1 A2[0C710000]            	mov	[time_seconds], al 
  1652 000009E6 B002                    	mov	al, CMOS_MINUTES
  1653 000009E8 E83B010000              	call	CMOS_READ
  1654 000009ED A2[0D710000]            	mov	[time_minutes], al 
  1655 000009F2 B004                    	mov	al, CMOS_HOURS
  1656 000009F4 E82F010000              	call	CMOS_READ
  1657 000009F9 A2[0E710000]                    mov     [time_hours], al
  1658 000009FE B006                    	mov	al, CMOS_DAY_WEEK 
  1659 00000A00 E823010000              	call	CMOS_READ
  1660 00000A05 A2[0F710000]            	mov	[date_wday], al
  1661 00000A0A B007                     	mov	al, CMOS_DAY_MONTH
  1662 00000A0C E817010000              	call	CMOS_READ
  1663 00000A11 A2[10710000]            	mov	[date_day], al
  1664 00000A16 B008                    	mov	al, CMOS_MONTH
  1665 00000A18 E80B010000              	call	CMOS_READ
  1666 00000A1D A2[11710000]            	mov	[date_month], al
  1667 00000A22 B009                    	mov	al, CMOS_YEAR
  1668 00000A24 E8FF000000              	call	CMOS_READ
  1669 00000A29 A2[12710000]            	mov	[date_year], al
  1670 00000A2E B032                    	mov	al, CMOS_CENTURY
  1671 00000A30 E8F3000000              	call	CMOS_READ
  1672 00000A35 A2[13710000]            	mov	[date_century], al
  1673                                  	;
  1674 00000A3A B000                    	mov	al, CMOS_SECONDS
  1675 00000A3C E8E7000000              	call 	CMOS_READ
  1676 00000A41 3A05[0C710000]          	cmp	al, [time_seconds]
  1677 00000A47 758A                    	jne	short time_of_day
  1678                                  
  1679                                  rtc_retn:
  1680 00000A49 C3                      	retn
  1681                                  
  1682                                  rtci_default:
  1683                                  	; 23/02/2022 (Temporary!)
  1684                                  	; (default real time clock handler in multitasking mode)
  1685                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1686 00000A4A FF05[54710000]          	inc	dword [rtc_ticks] ; real time clock counter
  1687                                  			; (not used in anywhere of kernel for now!)
  1688 00000A50 C3                      	retn
  1689                                  
  1690                                  rtc_p:
  1691                                  	; 27/12/2021 (Retro UNIX 386 v1.2)
  1692                                  	; 07/09/2014
  1693                                  	; 29/08/2014
  1694                                  	; 27/08/2014
  1695                                  	; 25/08/2014
  1696                                   	; Print Real Time Clock content
  1697                                  	;
  1698                                  	;
  1699 00000A51 E87DFFFFFF              	call	time_of_day
  1700 00000A56 72F1                    	jc	short rtc_retn
  1701                                  	;
  1702 00000A58 3A05[D86C0000]          	cmp	al, [ptime_seconds]
  1703 00000A5E 74E9                            je      short rtc_retn ; 29/08/2014
  1704                                  	;
  1705 00000A60 A2[D86C0000]            	mov	[ptime_seconds], al
  1706                                  	;
  1707 00000A65 A0[13710000]            	mov	al, [date_century]
  1708 00000A6A E8EA000000              	call	bcd_to_ascii
  1709 00000A6F 66A3[A56C0000]          	mov	[datestr+6], ax
  1710 00000A75 A0[12710000]            	mov	al, [date_year]
  1711 00000A7A E8DA000000              	call	bcd_to_ascii
  1712 00000A7F 66A3[A76C0000]          	mov	[datestr+8], ax
  1713 00000A85 A0[11710000]            	mov	al, [date_month]
  1714 00000A8A E8CA000000              	call	bcd_to_ascii
  1715 00000A8F 66A3[A26C0000]          	mov	[datestr+3], ax
  1716 00000A95 A0[10710000]            	mov	al, [date_day]
  1717 00000A9A E8BA000000              	call	bcd_to_ascii
  1718 00000A9F 66A3[9F6C0000]          	mov	[datestr], ax
  1719                                  	;
  1720 00000AA5 0FB61D[0F710000]        	movzx	ebx, byte [date_wday]
  1721 00000AAC C0E302                  	shl 	bl, 2
  1722 00000AAF 81C3[B86C0000]          	add	ebx, daytmp
  1723 00000AB5 8B03                    	mov	eax, [ebx]
  1724 00000AB7 A3[AA6C0000]            	mov	[daystr], eax
  1725                                  	;
  1726 00000ABC A0[0E710000]            	mov	al, [time_hours]
  1727 00000AC1 E893000000              	call	bcd_to_ascii
  1728 00000AC6 66A3[AE6C0000]          	mov	[timestr], ax
  1729 00000ACC A0[0D710000]            	mov	al, [time_minutes]
  1730 00000AD1 E883000000              	call	bcd_to_ascii
  1731 00000AD6 66A3[B16C0000]          	mov	[timestr+3], ax
  1732 00000ADC A0[0C710000]            	mov	al, [time_seconds]
  1733 00000AE1 E873000000              	call	bcd_to_ascii
  1734 00000AE6 66A3[B46C0000]          	mov	[timestr+6], ax
  1735                                  	;		
  1736 00000AEC BE[8D6C0000]            	mov	esi, rtc_msg ; message offset
  1737                                  	; 23/02/2015
  1738 00000AF1 52                      	push	edx
  1739 00000AF2 51                      	push	ecx
  1740                                  	; 07/09/2014
  1741                                  	;mov	bx, 2	; Video page 2
  1742                                  	; 27/12/2021
  1743 00000AF3 29DB                    	sub	ebx, ebx
  1744                                  	;mov	bl, 2
  1745                                  	; 15/02/2022
  1746 00000AF5 B307                    	mov	bl, 7	; Video page 7
  1747                                  prtmsg:
  1748 00000AF7 AC                      	lodsb
  1749 00000AF8 08C0                    	or	al, al
  1750 00000AFA 740D                    	jz	short prtmsg_ok
  1751 00000AFC 56                      	push	esi
  1752                                  	;push	bx
  1753 00000AFD 53                              push	ebx ; 27/12/2021
  1754 00000AFE B43F                    	mov	ah, 3Fh	; cyan (6) background, 
  1755                                  			; white (F) forecolor
  1756 00000B00 E8BF080000              	call 	write_tty
  1757                                  	;pop	bx
  1758 00000B05 5B                      	pop	ebx ; 27/12/2021
  1759 00000B06 5E                      	pop	esi
  1760 00000B07 EBEE                    	jmp	short prtmsg
  1761                                  	;
  1762                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1763                                  	;call	printk
  1764                                  prtmsg_ok:
  1765                                  	; 07/09/2014
  1766                                  	;xor	dx, dx		; column 0, row 0
  1767                                  	; 27/12/2021
  1768 00000B09 31D2                    	xor	edx, edx
  1769 00000B0B E8BE090000              	call	set_cpos	; set curspor position to 0,0 
  1770                                  	; 23/02/2015
  1771 00000B10 59                      	pop	ecx
  1772 00000B11 5A                      	pop	edx
  1773 00000B12 C3                      	retn
  1774                                  
  1775                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1776                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1777                                  default_irq7:
  1778                                  	; 04/12/2021
  1779                                  	;push	ax
  1780 00000B13 50                      	push	eax
  1781 00000B14 B00B                    	mov	al, 0Bh  ; In-Service register
  1782 00000B16 E620                    	out	20h, al
  1783 00000B18 EB00                            jmp short $+2
  1784 00000B1A EB00                    	jmp short $+2
  1785 00000B1C E420                    	in	al, 20h
  1786 00000B1E 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1787 00000B20 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1788 00000B22 B020                            mov     al, 20h ; EOI
  1789 00000B24 E620                    	out	20h, al 
  1790                                  irq7_iret:
  1791                                  	;pop	ax
  1792                                  	; 04/12/2021
  1793 00000B26 58                      	pop	eax
  1794 00000B27 CF                      	iretd
  1795                                  	
  1796                                  	; 04/12/2021
  1797                                  	; 22/08/2014
  1798                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1799                                  CMOS_READ:
  1800 00000B28 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1801 00000B29 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1802 00000B2B F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1803 00000B2C D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1804 00000B2E FA                      	cli		; DISABLE INTERRUPTS
  1805 00000B2F E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1806 00000B31 90                      	nop		; I/O DELAY
  1807 00000B32 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1808                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1809                                  	; 04/12/2021
  1810 00000B34 50                      	push	eax
  1811                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1812                                  		     ; ----- 10/06/85 (test4.asm)
  1813 00000B35 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1814                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1815 00000B37 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1816 00000B39 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1817                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1818                                  	; 04/12/2021
  1819 00000B3B 58                      	pop	eax
  1820 00000B3C 9D                      	popf	
  1821 00000B3D C3                      	retn		; RETURN WITH FLAGS RESTORED
  1822                                  
  1823                                  	; 22/08/2014
  1824                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1825                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1826 00000B3E 51                      	push	ecx
  1827 00000B3F B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1828                                  		; mov cx, 800	
  1829                                  UPD_10:
  1830 00000B44 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1831 00000B46 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1832 00000B47 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1833 00000B4C A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1834 00000B4E 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1835 00000B50 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1836 00000B51 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1837 00000B53 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1838                                  		; xor ax, ax
  1839 00000B55 F9                      	stc				; SET CARRY FOR ERROR
  1840                                  UPD_90:
  1841 00000B56 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1842 00000B57 FA                      	cli				; INTERRUPTS OFF DURING SET
  1843 00000B58 C3                      	retn				; RETURN WITH CY FLAG SET
  1844                                  
  1845                                  bcd_to_ascii:
  1846                                  	; 25/08/2014
  1847                                  	; INPUT ->
  1848                                  	;	al = Packed BCD number
  1849                                  	; OUTPUT ->
  1850                                  	;	ax  = ASCII word/number
  1851                                  	;
  1852                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1853                                  	;
  1854 00000B59 D410                    	db	0D4h, 10h		; Undocumented inst. AAM
  1855                                  					; AH = AL / 10h
  1856                                  					; AL = AL MOD 10h
  1857 00000B5B 660D3030                	or	ax, '00'		; Make it ASCII based
  1858                                  
  1859 00000B5F 86E0                            xchg	ah, al 
  1860                                  	
  1861 00000B61 C3                      	retn	
  1862                                  	
  1863                                  
  1864                                  %include 'keyboard.s' ; 07/03/2015
  1865                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1866                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1867                              <1> ; ****************************************************************************
  1868                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1869                              <1> ; Last Modification: 23/02/2022
  1870                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1871                              <1> ;
  1872                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1873                              <1> 
  1874                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  1875                              <1> ; 30/06/2015
  1876                              <1> ; 11/03/2015
  1877                              <1> ; 28/02/2015
  1878                              <1> ; 25/02/2015
  1879                              <1> ; 20/02/2015
  1880                              <1> ; 18/02/2015
  1881                              <1> ; 03/12/2014
  1882                              <1> ; 07/09/2014
  1883                              <1> ; KEYBOARD INTERRUPT HANDLER
  1884                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1885                              <1> 
  1886                              <1> ;getch:
  1887                              <1> ;	; 18/02/2015
  1888                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1889                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1890                              <1> ;	; routine, later... (multi tasking ability)
  1891                              <1> ;	; 28/02/2015
  1892                              <1> ;	sti	; enable interrupts
  1893                              <1> ;	;
  1894                              <1> ;	;push	esi
  1895                              <1> ;	;push	ebx
  1896                              <1> ;	;xor	ebx, ebx
  1897                              <1> ;	;mov	bl, [ptty]  ; active_page
  1898                              <1> ;	;mov	esi, ebx
  1899                              <1> ;	;shl 	si, 1
  1900                              <1> ;	;add	esi, ttychr
  1901                              <1> ;getch_1:
  1902                              <1> ;	;mov	ax, [esi]
  1903                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1904                              <1> ;	and	ax, ax
  1905                              <1> ;	jz	short getch_2
  1906                              <1> ;	mov	word [ttychr], 0
  1907                              <1> ;	;mov	word [esi], 0
  1908                              <1> ;	;pop	ebx
  1909                              <1> ;	;pop	esi
  1910                              <1> ;	retn
  1911                              <1> ;getch_2:
  1912                              <1> ;	hlt	; not proper for multi tasking!
  1913                              <1> ;		; (temporary halt for now)
  1914                              <1> ;		; 'sleep' on tty 
  1915                              <1> ;		; will (must) be located here		
  1916                              <1> ;	nop
  1917                              <1> ;	jmp	short getch_1
  1918                              <1> 
  1919                              <1> keyb_int:
  1920                              <1> 	; 23/02/2022
  1921                              <1> 	; 30/06/2015
  1922                              <1> 	; 25/02/2015
  1923                              <1> 	; 20/02/2015
  1924                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1925                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1926                              <1> 	; 30/06/2014
  1927                              <1> 	; 10/05/2013	
  1928                              <1>       	; Retro Unix 8086 v1 feature only!
  1929                              <1> 	; 03/03/2014
  1930                              <1> 	
  1931 00000B62 1E                  <1> 	push	ds
  1932 00000B63 53                  <1> 	push	ebx
  1933 00000B64 50                  <1> 	push	eax
  1934                              <1> 	;
  1935                              <1> 	; 23/02/2022
  1936 00000B65 9C                  <1> 	pushfd
  1937 00000B66 0E                  <1> 	push	cs
  1938                              <1> 	;mov	ax, KDATA
  1939 00000B67 31C0                <1> 	xor	eax, eax
  1940 00000B69 B010                <1> 	mov	al, KDATA
  1941 00000B6B 8ED8                <1> 	mov	ds, ax
  1942                              <1> 	;
  1943                              <1> 	;pushfd
  1944                              <1> 	;push	cs
  1945 00000B6D E810020000          <1> 	call	kb_int   ; int_09h
  1946                              <1> 	;
  1947 00000B72 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1948                              <1> 	;call	getc
  1949 00000B74 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1950 00000B79 744E                <1> 	jz	short keyb_int4
  1951                              <1> 	;
  1952 00000B7B B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1953                              <1> 	;call	getc
  1954 00000B7D E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1955                              <1> 	;
  1956                              <1> 	; 20/02/2015
  1957 00000B82 0FB61D[C6700000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1958                              <1> 	;
  1959 00000B89 20C0                <1> 	and 	al, al
  1960 00000B8B 751D                <1> 	jnz	short keyb_int1
  1961                              <1> 	;
  1962 00000B8D 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1963 00000B90 7218                <1> 	jb	short keyb_int1
  1964 00000B92 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1965 00000B95 7713                <1> 	ja	short keyb_int1
  1966                              <1> 	;
  1967 00000B97 88D8                <1> 	mov	al, bl
  1968 00000B99 0468                <1> 	add	al, 68h
  1969 00000B9B 38E0                <1> 	cmp	al, ah
  1970 00000B9D 7409                <1> 	je	short keyb_int0
  1971 00000B9F 88E0                <1> 	mov	al, ah
  1972 00000BA1 2C68                <1> 	sub	al, 68h
  1973 00000BA3 E83F0A0000          <1> 	call	tty_sw
  1974                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1975                              <1> keyb_int0: ; 30/06/2015
  1976                              <1> 	;xor	ax, ax
  1977                              <1> 	; 23/02/2022
  1978 00000BA8 31C0                <1> 	xor	eax, eax
  1979                              <1> keyb_int1:
  1980 00000BAA D0E3                <1> 	shl	bl, 1
  1981 00000BAC 81C3[C8700000]      <1> 	add	ebx, ttychr
  1982                              <1> 	;
  1983                              <1> 	;23/02/2022
  1984 00000BB2 09C0                <1> 	or	eax, eax
  1985                              <1> 	;or	ax, ax
  1986 00000BB4 7406                <1> 	jz	short keyb_int2
  1987                              <1> 	;
  1988 00000BB6 66833B00            <1> 	cmp 	word [ebx], 0
  1989 00000BBA 7703                <1>         ja      short keyb_int3 
  1990                              <1> keyb_int2:
  1991 00000BBC 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1992                              <1> 			   ; and scan code of the character
  1993                              <1> 			   ; for current tty (or last tty
  1994                              <1> 			   ; just before tty switch).
  1995                              <1> keyb_int3:
  1996 00000BBF A0[C6700000]        <1>         mov     al, [ptty]
  1997 00000BC4 E828450000          <1> 	call	wakeup
  1998                              <1> 	;
  1999                              <1> keyb_int4:
  2000 00000BC9 58                  <1> 	pop	eax
  2001 00000BCA 5B                  <1> 	pop	ebx
  2002 00000BCB 1F                  <1> 	pop	ds
  2003 00000BCC CF                  <1> 	iret
  2004                              <1> 
  2005                              <1> ; 18/02/2015
  2006                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2007                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2008                              <1> ; scancode and ascii code of the character 
  2009                              <1> ; in the tty input (ttychr) buffer. 
  2010                              <1> ; Test procedures must call 'getch' for tty input
  2011                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2012                              <1> ; due to infinite (key press) waiting loop.
  2013                              <1> ; 
  2014                              <1> ; 03/12/2014
  2015                              <1> ; 26/08/2014
  2016                              <1> ; KEYBOARD I/O
  2017                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2018                              <1> 
  2019                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2020                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2021                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2022                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2023                              <1> 
  2024                              <1> int_16h: ; 30/06/2015
  2025                              <1> ;getc:
  2026 00000BCD 9C                  <1> 	pushfd	; 28/08/2014
  2027 00000BCE 0E                  <1> 	push 	cs
  2028 00000BCF E826000000          <1> 	call 	getc_int
  2029 00000BD4 C3                  <1> 	retn
  2030                              <1> 
  2031                              <1> ; 05/12/2021
  2032                              <1> 
  2033                              <1> 	;-----	SHIFT STATUS
  2034                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2035 00000BD5 8A25[C46A0000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2036 00000BDB 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2037                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2038                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2039 00000BDE C0E405              <1>         shl	ah, 5
  2040 00000BE1 A0[C46A0000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2041 00000BE6 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2042 00000BE8 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2043 00000BEA A0[C66A0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2044 00000BEF 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2045 00000BF1 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2046                              <1> _K3:
  2047 00000BF3 A0[C36A0000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2048 00000BF8 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2049                              <1> 
  2050                              <1> getc_int:
  2051                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2052                              <1> 	; 28/02/2015
  2053                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2054                              <1> 	;	      instead of pc-at bios - 1985-)
  2055                              <1> 	; 28/08/2014 (_k1d)
  2056                              <1> 	; 30/06/2014
  2057                              <1> 	; 03/03/2014
  2058                              <1> 	; 28/02/2014
  2059                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2060                              <1> 	; rombios source code (21/04/1986)
  2061                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2062                              <1> 	;
  2063                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2064                              <1> 	;
  2065                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2066                              <1> 	; KEYBOARD I/O								      :
  2067                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2068                              <1> 	; INPUT									      :
  2069                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2070                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2071                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2072                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2073                              <1> 	;-----------------------------------------------------------------------------:
  2074                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2075                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2076                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2077                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2078                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2079                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2080                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2081                              <1> 	;-----------------------------------------------------------------------------:	
  2082                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2083                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2084                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2085                              <1> 	;-----------------------------------------------------------------------------:	
  2086                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2087                              <1> 	;	      (AL) = 05H                                                      :
  2088                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2089                              <1> 	;		       							      :
  2090                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2091                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2092                              <1> 	;                     --------------------------------------------            :
  2093                              <1> 	;			00H        30.0        10H        7.5                 :
  2094                              <1> 	;			01H        26.7        11H        6.7                 :
  2095                              <1> 	;			02H        24.0        12H        6.0                 :
  2096                              <1> 	;			03H        21.8        13H        5.5                 :
  2097                              <1> 	;			04H        20.0        14H        5.0                 :
  2098                              <1> 	;			05H        18.5        15H        4.6                 :
  2099                              <1> 	;			06H        17.1        16H        4.3                 :
  2100                              <1> 	;			07H        16.0        17H        4.0                 :
  2101                              <1> 	;			08H        15.0        18H        3.7                 :
  2102                              <1> 	;			09H        13.3        19H        3.3                 :
  2103                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2104                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2105                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2106                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2107                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2108                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2109                              <1> 	;									      :
  2110                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2111                              <1> 	;		       							      :
  2112                              <1> 	;                     REGISTER     DELAY                                      :
  2113                              <1> 	;                      VALUE       VALUE                                      :
  2114                              <1> 	;                     ------------------                                      :
  2115                              <1> 	;			00H        250 ms                                     :
  2116                              <1> 	;			01H        500 ms                                     :
  2117                              <1> 	;			02H        750 ms                                     :
  2118                              <1> 	;			03H       1000 ms                                     :
  2119                              <1> 	;-----------------------------------------------------------------------------:
  2120                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2121                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2122                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2123                              <1> 	;		           (CH) = SCAN CODE                                   :
  2124                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2125                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2126                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2127                              <1> 	;-----------------------------------------------------------------------------:		
  2128                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2129                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2130                              <1> 	;-----------------------------------------------------------------------------:
  2131                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2132                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2133                              <1> 	;-----------------------------------------------------------------------------:	
  2134                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2135                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2136                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2137                              <1> 	; OUTPUT					                              :
  2138                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2139                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2140                              <1> 	;------------------------------------------------------------------------------
  2141                              <1> 	
  2142 00000BFA FB                  <1> 	sti				; INTERRUPTS BACK ON
  2143 00000BFB 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2144 00000BFC 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2145                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2146 00000BFD 66BB1000            <1>         mov     bx, KDATA 
  2147 00000C01 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2148 00000C03 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2149 00000C05 742D                <1> 	jz	short _K1		; ASCII_READ
  2150 00000C07 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2151 00000C09 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2152 00000C0B FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2153 00000C0D 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2154 00000C0F FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2155 00000C11 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2156 00000C13 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2157 00000C16 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2158                              <1> _KIO1:	
  2159 00000C18 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2160 00000C1B 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2161 00000C1D FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2162 00000C1F 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2163 00000C21 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2164 00000C23 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2165                              <1> _KIO_EXIT:
  2166                              <1> 	;pop	ecx			; RECOVER REGISTER
  2167 00000C25 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2168 00000C26 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2169 00000C27 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2170                              <1> 
  2171                              <1> 	;-----	ASCII CHARACTER
  2172                              <1> _K1E:	
  2173 00000C28 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2174 00000C2D E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2175 00000C32 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2176                              <1> _K1:	
  2177 00000C34 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2178 00000C39 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2179 00000C3E 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2180                              <1> _K1A:
  2181 00000C40 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2182                              <1> 
  2183                              <1> 	;-----	ASCII STATUS
  2184                              <1> _K2E:	
  2185 00000C42 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2186 00000C47 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2187 00000C49 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2188 00000C4A E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2189 00000C4F EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2190                              <1> _K2:	
  2191 00000C51 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2192 00000C56 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2193 00000C58 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2194 00000C59 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2195 00000C5E 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2196 00000C60 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2197 00000C61 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2198 00000C66 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2199                              <1> _K2A:
  2200 00000C68 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2201                              <1> _K2B:
  2202                              <1> 	;pop	ecx			; RECOVER REGISTER
  2203 00000C69 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2204 00000C6A 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2205 00000C6B CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2206                              <1> 
  2207                              <1> ; 05/12/2021
  2208                              <1> ;	;-----	SHIFT STATUS
  2209                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2210                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2211                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2212                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2213                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2214                              <1> ;       shl	ah, 5
  2215                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2216                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2217                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2218                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2219                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2220                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2221                              <1> ;_K3:
  2222                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2223                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2224                              <1> 
  2225                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2226                              <1> _K300:
  2227 00000C6E 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2228 00000C70 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2229 00000C72 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2230 00000C75 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2231 00000C77 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2232 00000C7A 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2233 00000C7C B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2234 00000C7E E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2235                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2236                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2237 00000C83 C0E705              <1> 	shl	bh, 5
  2238 00000C86 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2239 00000C88 08F8                <1> 	or	al, bh			; AND DELAY
  2240 00000C8A E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2241 00000C8F EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2242                              <1> 
  2243                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2244                              <1> _K500:
  2245 00000C91 56                  <1> 	push	esi			; SAVE SI (esi)
  2246 00000C92 FA                  <1> 	cli				; 
  2247 00000C93 8B1D[D46A0000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2248 00000C99 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2249 00000C9B E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2250 00000CA0 3B1D[D06A0000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2251 00000CA6 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2252 00000CA8 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2253 00000CAB 891D[D46A0000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2254 00000CB1 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2255 00000CB3 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2256                              <1> _K502:
  2257 00000CB5 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2258                              <1> _K504:
  2259 00000CB7 FB                  <1> 	sti				
  2260 00000CB8 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2261 00000CB9 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2262                              <1> 
  2263                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2264                              <1> _K1S:
  2265 00000CBE FA                  <1> 	cli	; 03/12/2014
  2266 00000CBF 8B1D[D06A0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2267 00000CC5 3B1D[D46A0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2268                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2269 00000CCB 750F                <1> 	jne	short _k1x ; 03/12/2014
  2270                              <1> 	;
  2271                              <1> 	; 03/12/2014
  2272                              <1> 	; 28/08/2014
  2273                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2274                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2275                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2276                              <1> _K1T:                                   ; ASCII READ
  2277 00000CCD FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2278 00000CCE 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2279                              <1> _K1U:	
  2280 00000CCF FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2281 00000CD0 8B1D[D06A0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2282 00000CD6 3B1D[D46A0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2283                              <1> _k1x:
  2284 00000CDC 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2285 00000CDD 9C                  <1> 	pushf				; SAVE FLAGS
  2286 00000CDE E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2287 00000CE3 8A1D[C56A0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2288 00000CE9 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2289 00000CEB 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2290 00000CEE 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2291 00000CF0 E86E060000          <1> 	call	SND_LED1
  2292 00000CF5 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2293                              <1> _K1V:
  2294 00000CF6 9D                  <1> 	popf				; RESTORE FLAGS
  2295 00000CF7 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2296 00000CF8 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2297                              <1> 	;
  2298 00000CFA 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2299 00000CFD E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2300 00000D02 891D[D06A0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2301 00000D08 C3                  <1> 	retn				; RETURN
  2302                              <1> 
  2303                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2304                              <1> _K2S:
  2305 00000D09 FA                  <1> 	cli				; INTERRUPTS OFF
  2306 00000D0A 8B1D[D06A0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2307 00000D10 3B1D[D46A0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2308 00000D16 668B03              <1> 	mov	ax, [ebx]
  2309 00000D19 9C                  <1> 	pushf				; SAVE FLAGS
  2310                              <1> 	;push	ax			; SAVE CODE
  2311                              <1> 	; 05/12/2021
  2312 00000D1A 50                  <1> 	push	eax
  2313 00000D1B E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2314 00000D20 8A1D[C56A0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2315 00000D26 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2316 00000D28 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2317 00000D2B 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2318 00000D2D E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2319                              <1> _K2T:
  2320                              <1> 	;pop	ax			; RESTORE CODE
  2321                              <1> 	; 05/12/2021
  2322 00000D32 58                  <1> 	pop	eax
  2323 00000D33 9D                  <1> 	popf				; RESTORE FLAGS
  2324 00000D34 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2325 00000D35 C3                  <1> 	retn				; RETURN
  2326                              <1> 
  2327                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2328                              <1> _KIO_E_XLAT:
  2329 00000D36 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2330 00000D38 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2331 00000D3A 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2332 00000D3C 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2333 00000D3E 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2334                              <1> _KIO_E_RET:				
  2335 00000D40 C3                  <1> 	retn				; GO BACK
  2336                              <1> 
  2337                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2338                              <1> _KIO_S_XLAT:
  2339 00000D41 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2340 00000D44 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2341 00000D46 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2342 00000D48 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2343 00000D4A 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2344 00000D4C 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2345 00000D4E B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2346                              <1> _kio_ret: ; 03/12/2014
  2347 00000D50 F8                  <1> 	clc
  2348 00000D51 C3                  <1> 	retn
  2349                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2350                              <1> _KIO_S1:				
  2351 00000D52 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2352                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2353 00000D54 C3                  <1> 	retn
  2354                              <1> _KIO_S2:		
  2355 00000D55 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2356 00000D58 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2357 00000D5A 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2358 00000D5C 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2359 00000D5E 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2360 00000D60 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2361 00000D62 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2362                              <1> _KIO_S3:
  2363 00000D64 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2364                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2365 00000D66 75E8                <1> 	jne	short _kio_ret
  2366 00000D68 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2367 00000D6A 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2368 00000D6C 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2369                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2370                              <1> _KIO_USE:
  2371                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2372 00000D6E C3                  <1> 	retn				; RETURN	
  2373                              <1> _KIO_DIS:
  2374 00000D6F F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2375 00000D70 C3                  <1> 	retn				; RETURN
  2376                              <1> 
  2377                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2378                              <1> _K4:    
  2379 00000D71 43                  <1> 	inc     ebx
  2380 00000D72 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2381 00000D73 3B1D[CC6A0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2382                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2383 00000D79 7206                <1> 	jb	short _K5
  2384 00000D7B 8B1D[C86A0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2385                              <1> _K5:
  2386 00000D81 C3                  <1> 	retn
  2387                              <1> 
  2388                              <1> ; 20/02/2015
  2389                              <1> ; 05/12/2014
  2390                              <1> ; 26/08/2014
  2391                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2392                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2393                              <1> ;
  2394                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2395                              <1> ; rombios source code (06/10/1985)
  2396                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2397                              <1> 
  2398                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2399                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2400                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2401                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2402                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2403                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2404                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2405                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2406                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2407                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2408                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2409                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2410                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2411                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2412                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2413                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2414                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2415                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2416                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2417                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2418                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2419                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2420                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2421                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2422                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2423                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2424                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2425                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2426                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2427                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2428                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2429                              <1> F11_M		equ	87		; F11 KEY MAKE
  2430                              <1> F12_M		equ	88		; F12 KEY MAKE
  2431                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2432                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2433                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2434                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2435                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2436                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2437                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2438                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2439                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2440                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2441                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2442                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2443                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2444                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2445                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2446                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2447                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2448                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2449                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2450                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2451                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2452                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2453                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2454                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2455                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2456                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2457                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2458                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2459                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2460                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2461                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2462                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2463                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2464                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2465                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2466                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2467                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2468                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2469                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2470                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2471                              <1> ;
  2472                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2473                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2474                              <1> INTA00		equ	020h		; 8259 PORT
  2475                              <1> 
  2476                              <1> 
  2477                              <1> kb_int:
  2478                              <1> 
  2479                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2480                              <1> ; 17/10/2015 ('ctrlbrk') 
  2481                              <1> ; 05/12/2014
  2482                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2483                              <1> 	;	      instead of pc-at bios - 1985-)
  2484                              <1> ; 26/08/2014
  2485                              <1> ;
  2486                              <1> ; 03/06/86  KEYBOARD BIOS
  2487                              <1> ;
  2488                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2489                              <1> ;										;
  2490                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2491                              <1> ;										;
  2492                              <1> ;--------------------------------------------------------------------------------
  2493                              <1> 
  2494                              <1> KB_INT_1:
  2495 00000D82 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2496                              <1> 	;push	ebp
  2497 00000D83 50                  <1> 	push	eax
  2498 00000D84 53                  <1> 	push	ebx
  2499 00000D85 51                  <1> 	push	ecx
  2500 00000D86 52                  <1> 	push	edx
  2501 00000D87 56                  <1> 	push	esi
  2502 00000D88 57                  <1> 	push	edi
  2503 00000D89 1E                  <1> 	push	ds
  2504 00000D8A 06                  <1> 	push	es
  2505 00000D8B FC                  <1> 	cld				; FORWARD DIRECTION
  2506 00000D8C 66B81000            <1> 	mov	ax, KDATA
  2507 00000D90 8ED8                <1> 	mov	ds, ax
  2508 00000D92 8EC0                <1> 	mov	es, ax
  2509                              <1> 	;
  2510                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2511 00000D94 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2512 00000D96 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2513 00000D9B FA                  <1> 	cli				; DISABLE INTERRUPTS
  2514 00000D9C B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2515                              <1> KB_INT_01:
  2516 00000DA1 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2517 00000DA3 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2518 00000DA5 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2519                              <1> 	;
  2520                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2521 00000DA7 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2522                              <1> 	;
  2523                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2524                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2525                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2526                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2527                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2528                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2529                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2530                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2531                              <1> 	;
  2532                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2533                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2534 00000DA9 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2535 00000DAA 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2536 00000DAC 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2537                              <1> 	;
  2538                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2539 00000DAE 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2540 00000DB0 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2541                              <1> 	;
  2542                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2543 00000DB2 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2544 00000DB3 800D[C56A0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2545 00000DBA E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2546                              <1> 	;
  2547                              <1> 	;-----	RESEND THE LAST BYTE
  2548                              <1> KB_INT_4:
  2549 00000DBF FA                  <1> 	cli				; DISABLE INTERRUPTS
  2550 00000DC0 800D[C56A0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2551 00000DC7 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2552                              <1> 	;
  2553                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2554                              <1> KB_INT_2:
  2555                              <1> 	;push 	ax			; SAVE DATA IN
  2556                              <1> 	; 05/12/2021
  2557 00000DCC 50                  <1> 	push	eax
  2558 00000DCD E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2559 00000DD2 8A1D[C56A0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2560 00000DD8 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2561 00000DDA 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2562 00000DDD 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2563 00000DDF E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2564                              <1> UP0:
  2565                              <1> 	;pop	ax			; RESTORE DATA IN
  2566                              <1> 	; 05/12/2021
  2567 00000DE4 58                  <1> 	pop	eax
  2568                              <1> ;------------------------------------------------------------------------
  2569                              <1> ;	START OF KEY PROCESSING						;
  2570                              <1> ;------------------------------------------------------------------------
  2571 00000DE5 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2572                              <1> 	;
  2573                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2574 00000DE7 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2575                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2576                              <1> 	; 05/12/2021
  2577 00000DE9 7505                <1> 	jne	short K16
  2578 00000DEB E9ED040000          <1> 	jmp	K62
  2579                              <1> K16:	
  2580 00000DF0 8A3D[C66A0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2581                              <1> 	;
  2582                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2583 00000DF6 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2584 00000DF9 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2585 00000DFB 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2586 00000DFD 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2587 00000DFF 7507                <1> 	jne	short RST_RD_ID
  2588 00000E01 800D[C66A0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2589                              <1> RST_RD_ID:
  2590 00000E08 8025[C66A0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2591 00000E0F EB27                <1>         jmp    short ID_EX		; AND EXIT
  2592                              <1> 	; 05/12/2021
  2593                              <1> 	;jmp	K26
  2594                              <1> 	;
  2595                              <1> TST_ID_2:
  2596 00000E11 8025[C66A0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2597 00000E18 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2598 00000E1A 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2599 00000E1C 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2600 00000E1E 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2601                              <1> 	; 05/12/2021
  2602                              <1> 	;jne	K26
  2603                              <1> 	;
  2604                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2605 00000E20 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2606 00000E23 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2607 00000E25 800D[C36A0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2608 00000E2C E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2609                              <1> KX_BIT:
  2610 00000E31 800D[C66A0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2611 00000E38 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2612                              <1> 	;
  2613                              <1> NOT_ID:
  2614 00000E3D 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2615 00000E3F 750E                <1> 	jne	short TEST_E1
  2616 00000E41 800D[C66A0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2617 00000E48 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2618                              <1> 	; 05/12/2021
  2619 00000E4A E9DA010000          <1> 	jmp	K26A	
  2620                              <1> TEST_E1:	
  2621 00000E4F 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2622 00000E51 750C                <1> 	jne	short NOT_HC
  2623 00000E53 800D[C66A0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2624 00000E5A E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2625                              <1> 	;
  2626                              <1> NOT_HC:
  2627 00000E5F 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2628 00000E61 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2629 00000E64 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2630                              <1> 	;
  2631 00000E66 BF[AE690000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2632 00000E6B AE                  <1> 	scasb
  2633                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2634                              <1> 	; 05/12/2021
  2635 00000E6C 7458                <1> 	je	short K16B
  2636 00000E6E AE                  <1> 	scasb
  2637 00000E6F 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2638 00000E71 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2639                              <1> 	; 05/12/2021
  2640                              <1> 	;jmp	K26
  2641                              <1> 	;
  2642                              <1> NOT_LC_E0:
  2643 00000E73 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2644 00000E76 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2645 00000E78 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2646 00000E7D BF[AC690000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2647 00000E82 F2AE                <1> 	repne	scasb			; CHECK IT
  2648 00000E84 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2649                              <1> 	; 05/12/2021
  2650                              <1> 	;je	K26A			
  2651                              <1> 	;
  2652 00000E86 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2653 00000E88 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2654                              <1> 	; 05/12/2021
  2655                              <1> 	;jne	K26
  2656 00000E8A F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2657 00000E8D 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2658                              <1> 	; 05/12/2021
  2659                              <1> 	;jnz	K26
  2660                              <1>         ; 20/02/2015 
  2661 00000E8F F605[C46A0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2662 00000E96 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2663                              <1> 	; 05/12/2021
  2664                              <1> 	;jnz	K26
  2665 00000E98 E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2666                              <1> 	;
  2667                              <1> 	;-----	TEST FOR SYSTEM KEY
  2668                              <1> T_SYS_KEY:
  2669 00000E9D 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2670 00000E9F 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2671                              <1> 	;
  2672 00000EA1 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2673 00000EA4 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2674                              <1> 	;
  2675 00000EA6 F605[C46A0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2676 00000EAD 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2677                              <1> 	;jnz	K26			
  2678                              <1> 	;
  2679 00000EAF 800D[C46A0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2680 00000EB6 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2681 00000EB8 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2682                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2683 00000EBA B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2684 00000EBC E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2685                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2686                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2687                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2688                              <1> 	;INT	15H			; USER INTERRUPT	
  2689 00000EC1 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2690                              <1> 	;
  2691 00000EC6 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2692                              <1> 	;
  2693                              <1> K16C:
  2694 00000ECB 8025[C46A0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2695 00000ED2 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2696 00000ED4 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2697                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2698                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2699                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2700                              <1> 	;
  2701                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2702                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2703                              <1> 	;INT	15H			; USER INTERRUPT
  2704                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2705                              <1> 	;
  2706 00000ED6 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2707                              <1> 	;
  2708                              <1> 	;-----	TEST FOR SHIFT KEYS
  2709                              <1> K16A:
  2710 00000EDB 8A1D[C36A0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2711 00000EE1 BF[A8690000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2712 00000EE6 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2713 00000EEB F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2714 00000EED 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2715                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2716                              <1> 	; 05/12/2021
  2717 00000EEF 7405                <1> 	je	short K17
  2718 00000EF1 E914010000          <1> 	jmp	K25
  2719                              <1> 	;
  2720                              <1> 	;------	SHIFT KEY FOUND
  2721                              <1> K17:
  2722 00000EF6 81EF[A9690000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2723 00000EFC 8AA7[B0690000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2724 00000F02 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2725 00000F04 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2726                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2727                              <1> 	; 05/12/2021
  2728 00000F06 7405                <1> 	jz	short K17C
  2729 00000F08 E999000000          <1> 	jmp	K23
  2730                              <1> 	;
  2731                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2732                              <1> K17C:
  2733 00000F0D 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2734 00000F10 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2735                              <1> 	;
  2736                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2737 00000F12 0825[C36A0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2738 00000F18 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2739 00000F1A 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2740                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2741                              <1> 	; 05/12/2021
  2742 00000F1C E901010000          <1> 	jmp	K26
  2743                              <1> K17D:
  2744 00000F21 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2745 00000F24 740B                <1> 	jz 	short K17E		; NO, JUMP
  2746 00000F26 0825[C66A0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2747 00000F2C E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2748                              <1> K17E:
  2749 00000F31 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2750 00000F33 0825[C46A0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2751 00000F39 E9E4000000          <1> 	jmp	K26
  2752                              <1> 	;
  2753                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2754                              <1> K18:					; SHIFT-TOGGLE
  2755 00000F3E F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2756 00000F41 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2757                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2758                              <1> 	; 05/12/2021
  2759 00000F43 E9C2000000          <1> 	jmp	K25
  2760                              <1> K18A:
  2761 00000F48 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2762 00000F4A 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2763 00000F4C F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2764 00000F4F 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2765                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2766                              <1> 	; 05/12/2021
  2767 00000F51 E9B4000000          <1> 	jmp	K25
  2768                              <1> K18B:
  2769 00000F56 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2770 00000F59 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2771                              <1> K19:	
  2772 00000F5B F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2773 00000F5E 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2774 00000F60 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2775 00000F63 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2776                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2777 00000F65 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2778 00000F67 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2779                              <1> K21:					; MIGHT BE NUMERIC
  2780 00000F6C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2781 00000F6F 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2782                              <1> 	;
  2783                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2784 00000F71 8425[C46A0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2785                              <1> 	;jnz	K26
  2786                              <1> 	; 05/12/2021
  2787 00000F77 7405                <1> 	jz	short K22A
  2788 00000F79 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2789                              <1> K22A:
  2790 00000F7E 0825[C46A0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2791 00000F84 3025[C36A0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2792                              <1> 	;
  2793                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2794 00000F8A F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2795 00000F8D 7407                <1> 	jz	short K22B		; GO IF NOT
  2796                              <1> 	;
  2797                              <1> 	; 05/12/2021
  2798                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2799 00000F8F 50                  <1> 	push	eax
  2800 00000F90 E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2801                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2802 00000F95 58                  <1> 	pop	eax
  2803                              <1> K22B:
  2804 00000F96 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2805                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2806                              <1> 	; 05/12/2021
  2807 00000F98 7405                <1> 	je	short K22C
  2808 00000F9A E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2809                              <1> K22C:
  2810 00000F9F 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2811 00000FA1 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2812                              <1> 	;
  2813                              <1> 	;-----	BREAK SHIFT FOUND
  2814                              <1> K23:					; BREAK-SHIFT-FOUND
  2815 00000FA6 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2816 00000FA9 F6D4                <1> 	not	ah			; INVERT MASK
  2817 00000FAB 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2818 00000FAD 2025[C36A0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2819 00000FB3 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2820 00000FB6 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2821                              <1> 	;
  2822 00000FB8 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2823 00000FBB 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2824 00000FBD 2025[C66A0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2825 00000FC3 EB08                <1> 	jmp	short K23B		; CONTINUE
  2826                              <1> K23A:
  2827 00000FC5 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2828 00000FC7 2025[C46A0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2829                              <1> K23B:
  2830 00000FCD 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2831 00000FCF A0[C66A0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2832 00000FD4 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2833 00000FD6 0A05[C46A0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2834 00000FDC D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2835 00000FDE 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2836 00000FE0 0805[C36A0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2837 00000FE6 88E0                <1> 	mov	al, ah
  2838                              <1> K23D:
  2839 00000FE8 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2840 00000FEA 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2841                              <1> 	;	
  2842                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2843 00000FEC A0[C76A0000]        <1> 	mov	al, [ALT_INPUT]
  2844 00000FF1 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2845 00000FF3 8825[C76A0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2846 00000FF9 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2847 00000FFB 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2848 00000FFD E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2849                              <1> 	;
  2850                              <1> K24:					; BREAK-TOGGLE
  2851 00001002 2025[C46A0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2852 00001008 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2853                              <1> 	;
  2854                              <1> 	;-----	TEST FOR HOLD STATE
  2855                              <1> 					; AL, AH = SCAN CODE
  2856                              <1> K25:					; NO-SHIFT-FOUND
  2857 0000100A 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2858 0000100C 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2859 0000100E F605[C46A0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2860 00001015 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2861 00001017 3C45                <1> 	cmp	al, NUM_KEY
  2862 00001019 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2863 0000101B 8025[C46A0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2864                              <1> 	;
  2865                              <1> K26:
  2866 00001022 8025[C66A0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2867                              <1> K26A:					; INTERRUPT-RETURN
  2868 00001029 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2869 0000102A B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2870 0000102C E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2871                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2872 0000102E B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2873 00001030 E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2874                              <1> K27A:
  2875 00001035 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2876 00001036 07                  <1> 	pop	es			; RESTORE REGISTERS
  2877 00001037 1F                  <1> 	pop	ds
  2878 00001038 5F                  <1> 	pop	edi
  2879 00001039 5E                  <1> 	pop	esi
  2880 0000103A 5A                  <1> 	pop	edx
  2881 0000103B 59                  <1> 	pop	ecx
  2882 0000103C 5B                  <1> 	pop	ebx
  2883 0000103D 58                  <1> 	pop	eax
  2884                              <1> 	;pop	ebp
  2885 0000103E CF                  <1> 	iret				; RETURN
  2886                              <1> 
  2887                              <1> 	;-----	NOT IN	HOLD STATE
  2888                              <1> K28:					; NO-HOLD-STATE
  2889 0000103F 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2890 00001041 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2891                              <1> 	;
  2892 00001043 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2893 00001046 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2894                              <1>         ; 05/12/2021
  2895                              <1> 	;jz      K38
  2896                              <1> 	;
  2897 00001048 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2898 0000104B 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2899                              <1> 	; 28/02/2015
  2900 0000104D F605[C46A0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2901 00001054 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2902                              <1> 	; 05/12/2021
  2903                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2904                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2905 00001056 E9D1000000          <1> K28A:	jmp	K38
  2906                              <1> 	;
  2907                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2908                              <1> K29:					; TEST-RESET
  2909 0000105B F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2910 0000105E 740B                <1> 	jz	short K31		; NO_RESET
  2911 00001060 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2912 00001062 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2913                              <1> 	;
  2914                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2915                              <1>  	; 26/08/2014
  2916                              <1> cpu_reset:
  2917                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2918                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2919 00001064 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2920 00001066 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2921                              <1> khere:
  2922 00001068 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2923 00001069 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2924                              <1> 
  2925                              <1> 	;
  2926                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2927                              <1> K31:					; NO-RESET
  2928 0000106B 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2929 0000106D 7507                <1> 	jne	short K311		; NOT THERE
  2930 0000106F B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2931 00001071 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2932                              <1> K311:
  2933 00001076 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2934 00001078 7509                <1> 	jne	short K312		; NOT THERE
  2935 0000107A 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2936 0000107E E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2937                              <1> K312:
  2938 00001083 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2939 00001085 7471                <1>         je	short K37B              ; GO PROCESS
  2940 00001087 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2941 00001089 746D                <1>         je	short K37B              ; GO PROCESS
  2942                              <1> 	;
  2943                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2944                              <1> K32:					; ALT-KEY-PAD
  2945 0000108B BF[84690000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2946 00001090 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2947 00001095 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2948 00001097 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2949 00001099 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2950                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2951                              <1> 	; 05/12/2021
  2952 0000109C 751C                <1> 	jnz	short K32B
  2953 0000109E 81EF[85690000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2954 000010A4 A0[C76A0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2955 000010A9 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2956 000010AB F6E4                <1> 	mul	ah
  2957 000010AD 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2958 000010B0 A2[C76A0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2959                              <1> K32A:
  2960 000010B5 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2961                              <1> K32B:
  2962                              <1> 	; 05/12/2021
  2963 000010BA EB6A                <1> 	jmp	K37C
  2964                              <1> 	;
  2965                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2966                              <1> K33:					; NO-ALT-KEYPAD
  2967 000010BC C605[C76A0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2968 000010C3 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2969 000010C8 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2970 000010CA 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2971                              <1> 	;
  2972                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2973                              <1> K34:					; ALT-TOP-ROW
  2974 000010CC 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2975 000010CE 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2976 000010D0 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2977 000010D2 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2978 000010D4 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2979 000010D7 EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2980                              <1> 	;
  2981                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2982                              <1> K35:					; ALT-FUNCTION
  2983 000010D9 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2984 000010DB 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2985 000010DD 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2986 000010DF 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2987 000010E1 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2988 000010E4 EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2989                              <1> K35A:
  2990 000010E6 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2991 000010E9 7425                <1> 	jz	short K37		; NO, JUMP
  2992 000010EB 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2993 000010ED 7510                <1>         jne     short K35B              ; NOT THERE
  2994 000010EF 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2995 000010F3 E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2996                              <1> K37B:
  2997 000010F8 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2998 000010FA E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2999                              <1> K35B:
  3000 000010FF 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3001 00001101 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3002 00001103 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3003 00001105 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3004                              <1>         ; 05/12/2021
  3005                              <1> 	;jne	K26
  3006 00001107 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3007 0000110B E99C010000          <1> 	jmp	K57			; BUFFER FILL
  3008                              <1> K37:
  3009 00001110 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3010 00001112 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3011 00001114 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3012                              <1>         ;ja	short K32A		; IF SO, IGNORE
  3013 00001116 0F8706FFFFFF        <1>         ja      K26
  3014 0000111C 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3015                              <1> K37A:
  3016 0000111F B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3017 00001121 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3018                              <1> K37C:
  3019 00001126 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3020 00001128 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3021 0000112A EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3022                              <1> 	;
  3023                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3024                              <1> K38:					; NOT-ALT-SHIFT
  3025                              <1> 					; BL STILL HAS SHIFT FLAGS
  3026 0000112C F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3027 0000112F 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3028                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3029                              <1> 	; 05/12/2021
  3030 00001131 E9AB000000          <1> 	jmp	K44
  3031                              <1> 	;
  3032                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3033                              <1> 	;-----	TEST FOR BREAK
  3034                              <1> K38A:
  3035 00001136 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3036 00001138 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3037 0000113A F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3038 0000113D 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3039 0000113F F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3040 00001142 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3041                              <1> K38B:
  3042 00001144 8B1D[D06A0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3043 0000114A 891D[D46A0000]      <1> 	mov	[BUFFER_TAIL], ebx
  3044 00001150 C605[C26A0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3045                              <1> 	;
  3046                              <1> 	;-----	ENABLE KEYBOARD
  3047 00001157 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3048 00001159 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3049                              <1> 	;
  3050                              <1> 	; CTRL+BREAK code here !!!
  3051                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3052                              <1> 	; 17/10/2015	
  3053 0000115E E85B220000          <1> 	call	ctrlbrk ; control+break subroutine
  3054                              <1> 	;
  3055                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3056                              <1> 	; 05/12/2021
  3057 00001163 29C0                <1> 	sub	eax, eax
  3058 00001165 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3059                              <1> 	;
  3060                              <1> 	;-----	TEST FOR PAUSE
  3061                              <1> K39:					; NO_BREAK
  3062 0000116A F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3063 0000116D 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3064 0000116F 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3065 00001171 7533                <1> 	jne	short K41		; NO-PAUSE
  3066                              <1> K39P:
  3067 00001173 800D[C46A0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3068                              <1> 	;
  3069                              <1> 	;-----	ENABLE KEYBOARD
  3070 0000117A B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3071 0000117C E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3072                              <1> K39A:
  3073 00001181 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3074 00001183 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3075                              <1> 	;
  3076                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3077 00001185 803D[C06A0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3078 0000118C 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3079 0000118E 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3080 00001192 A0[C16A0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3081 00001197 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3082                              <1> 	;
  3083                              <1> K40:					; PAUSE-LOOP
  3084 00001198 F605[C46A0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3085 0000119F 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3086                              <1> 	;
  3087 000011A1 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3088                              <1>         ;
  3089                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3090                              <1> K41:					; NO-PAUSE
  3091 000011A6 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3092 000011A8 7513                <1> 	jne	short K42		; NOT-KEY-55
  3093 000011AA F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3094 000011AD 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3095 000011AF F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3096 000011B2 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3097                              <1> K41A:	
  3098 000011B4 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3099 000011B8 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3100                              <1> 	;
  3101                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3102                              <1> K42:					; NOT-KEY-55
  3103 000011BD 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3104 000011BF 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3105 000011C1 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3106 000011C3 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3107 000011C5 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3108 000011C8 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3109 000011CA 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3110 000011CE E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3111                              <1> K42A:
  3112                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3113 000011D3 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3114                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3115                              <1> 	;;jb	K56 ; 20/02/2015
  3116                              <1> 	;;jmp	K64 ; 20/02/2015
  3117                              <1> K42B:
  3118 000011D5 BB[B8690000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3119                              <1> 	;;jmp	K64
  3120                              <1> 	;jb	K56 ;; 20/02/2015	
  3121                              <1> 	; 05/12/2021
  3122 000011DA 7267                <1> 	jb	short K45F
  3123 000011DC E9B9000000          <1> 	jmp	K64	
  3124                              <1>         ;
  3125                              <1> 	;-----	NOT IN CONTROL SHIFT
  3126                              <1> K44:					; NOT-CTL-SHIFT
  3127 000011E1 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3128 000011E3 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3129 000011E5 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3130 000011E8 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3131 000011EA F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3132 000011ED 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3133 000011EF EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3134                              <1> K44A:
  3135 000011F1 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3136 000011F4 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3137                              <1> 	;
  3138                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3139                              <1> K44B:
  3140 000011F6 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3141 000011F8 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3142 000011FD B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3143 000011FF E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3144                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3145                              <1> 	;PUSH 	BP			; SAVE POINTER
  3146                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3147                              <1> 	;POP	BP			; RESTORE POINTER
  3148 00001201 8025[C66A0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3149 00001208 E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3150                              <1> 	;
  3151                              <1> 	;-----	HANDLE IN-CORE KEYS
  3152                              <1> K45:					; NOT-PRINT-SCREEN
  3153 0000120D 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3154 0000120F 7734                <1> 	ja	short K46		; JUMP IF NOT
  3155 00001211 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3156 00001213 7505                <1> 	jne	short K45A		; NO, JUMP
  3157 00001215 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3158 00001218 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3159                              <1> K45A:
  3160 0000121A B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3161 0000121F BF[8E690000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3162 00001224 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3163                              <1> 		; 20/02/2015
  3164 00001226 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3165                              <1> 	;
  3166 00001228 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3167 0000122B 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3168                              <1> K45B:
  3169 0000122D F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3170 00001230 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3171                              <1> 					; NO, LOWERCASE
  3172                              <1> K45C:
  3173 00001232 BB[106A0000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3174 00001237 EB51                <1> 	jmp	short K56	
  3175                              <1> K45D:					; ALMOST-CAPS-STATE
  3176 00001239 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3177 0000123C 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3178                              <1> K45E:
  3179 0000123E BB[686A0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3180 00001243 EB45                <1> K45F:	jmp	short K56
  3181                              <1> 	;
  3182                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3183                              <1> K46:					; NOT IN-CORE AREA
  3184 00001245 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3185                              <1> 	;ja	short K47		; JUMP IF NOT
  3186                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3187 00001247 7635                <1> 	jna	short K53		
  3188                              <1> 	;
  3189                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3190                              <1> K47:					; NOT F1 - F10
  3191 00001249 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3192 0000124B 772D                <1> 	ja	short K52		; JUMP IF NOT
  3193                              <1> 	;
  3194                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3195                              <1> K48:
  3196 0000124D 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3197 0000124F 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3198 00001251 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3199 00001253 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3200 00001255 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3201 00001258 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3202                              <1> 	;		
  3203 0000125A F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3204 0000125D 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3205 0000125F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3206                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3207 00001262 75DA                <1> 	jnz	short K45E
  3208                              <1> 	;
  3209                              <1> 	;-----	BASE CASE FOR KEYPAD
  3210                              <1> K49:					
  3211 00001264 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3212 00001266 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3213 00001268 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3214 0000126A EB40                <1> 	jmp	short K57		; BUFFER FILL
  3215                              <1> K49A:
  3216 0000126C BB[106A0000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3217 00001271 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3218                              <1> 	;
  3219                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3220                              <1> K50:					; ALMOST-NUM-STATE
  3221 00001273 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3222 00001276 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3223 00001278 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3224                              <1> 	;
  3225                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3226                              <1> K52:					; NOT A NUMPAD KEY
  3227 0000127A 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3228                              <1> 	;jne	short K53		; JUMP IF NOT
  3229                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3230 0000127C 74AF                <1> 	je	short K45B		
  3231                              <1> 	;
  3232                              <1> 	;-----	MUST BE F11 OR F12 
  3233                              <1> K53:					; F1 - F10 COME HERE, TOO
  3234 0000127E F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3235 00001281 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3236                              <1> 		; 20/02/2015 
  3237 00001283 BB[686A0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3238 00001288 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3239                              <1> 	;
  3240                              <1> 	;-----	TRANSLATE THE CHARACTER
  3241                              <1> K56:					; TRANSLATE-CHAR
  3242 0000128A FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3243 0000128C D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3244 0000128D F605[C66A0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3245 00001294 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3246 00001296 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3247 00001298 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3248                              <1> 	;
  3249                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3250                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3251 0000129A FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3252 0000129C D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3253 0000129D 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3254 0000129F B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3255 000012A1 F605[C66A0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3256 000012A8 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3257 000012AA B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3258                              <1> 	;
  3259                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3260                              <1> K57:					; BUFFER_FILL
  3261 000012AC 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3262 000012AE 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3263                              <1> 	; 05/12/2021
  3264                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3265 000012B0 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3266                              <1> 	; 05/12/2021
  3267 000012B3 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3268                              <1> 	;je	K26			; INTERRUPT_RETURN
  3269                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3270 000012B5 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3271                              <1> K61:					; NOT-CAPS-STATE
  3272 000012BA 8B1D[D46A0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3273 000012C0 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3274 000012C2 E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3275 000012C7 3B1D[D06A0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3276 000012CD 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3277 000012CF 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3278 000012D2 891D[D46A0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3279 000012D8 E945FDFFFF          <1> 	jmp	K26
  3280                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3281                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3282                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3283                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3284                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3285                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3286                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3287                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3288                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3289                              <1> 	;;jmp   K27                    
  3290                              <1> 	;
  3291                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3292                              <1> K62:
  3293 000012DD B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3294 000012DF E620                <1> 	out	INTA00, al
  3295 000012E1 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3296 000012E5 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3297 000012E7 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3298 000012EC E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3299                              <1> 
  3300                              <1> SHIP_IT:
  3301                              <1> 	;---------------------------------------------------------------------------------
  3302                              <1> 	; SHIP_IT
  3303                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3304                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3305                              <1> 	;---------------------------------------------------------------------------------
  3306                              <1> 	;
  3307                              <1> 	;push	ax			; SAVE DATA TO SEND
  3308                              <1> 	; 05/12/2021
  3309 000012F1 50                  <1> 	push	eax
  3310                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3311 000012F2 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3312                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3313 000012F3 B900000100          <1> 	mov	ecx, 10000h			
  3314                              <1> S10:
  3315 000012F8 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3316 000012FA A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3317 000012FC E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3318                              <1> 
  3319                              <1> 	;pop	ax			; GET DATA TO SEND
  3320                              <1> 	; 05/12/2021
  3321 000012FE 58                  <1> 	pop	eax
  3322 000012FF E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3323 00001301 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3324 00001302 C3                  <1> 	retn				; RETURN TO CALLER
  3325                              <1> 
  3326                              <1> SND_DATA:
  3327                              <1> 	; ---------------------------------------------------------------------------------
  3328                              <1> 	; SND_DATA
  3329                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3330                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3331                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3332                              <1> 	; ---------------------------------------------------------------------------------
  3333                              <1> 	;
  3334                              <1> 	;push	ax			; SAVE REGISTERS
  3335                              <1> 	;push	bx
  3336                              <1> 	; 05/12/2021
  3337 00001303 50                  <1> 	push	eax
  3338 00001304 53                  <1> 	push	ebx
  3339 00001305 51                  <1> 	push	ecx
  3340 00001306 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3341 00001308 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3342                              <1> SD0:
  3343 0000130A FA                  <1> 	cli				; DISABLE INTERRUPTS
  3344 0000130B 8025[C56A0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3345                              <1> 	;
  3346                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3347 00001312 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3348                              <1> SD5:
  3349 00001317 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3350 00001319 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3351 0000131B E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3352                              <1> 	;
  3353 0000131D 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3354 0000131F E660                <1> 	out	PORT_A, al		; SEND BYTE
  3355 00001321 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3356                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3357 00001322 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3358                              <1> SD1:
  3359 00001327 F605[C56A0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3360 0000132E 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3361 00001330 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3362                              <1> SD2:
  3363 00001332 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3364 00001334 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3365 00001336 800D[C56A0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3366 0000133D EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3367                              <1> SD3:
  3368 0000133F F605[C56A0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3369 00001346 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3370                              <1> SD4:	
  3371 00001348 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3372                              <1> 	;pop	bx
  3373                              <1> 	;pop	ax
  3374                              <1> 	; 05/12/2021
  3375 00001349 5B                  <1> 	pop	ebx
  3376 0000134A 58                  <1> 	pop	eax
  3377 0000134B C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3378                              <1> 
  3379                              <1> SND_LED:
  3380                              <1> 	; ---------------------------------------------------------------------------------
  3381                              <1> 	; SND_LED
  3382                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3383                              <1> 	;
  3384                              <1> 	;----------------------------------------------------------------------------------
  3385                              <1> 	;
  3386 0000134C FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3387 0000134D F605[C56A0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3388 00001354 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3389                              <1> 	;
  3390 00001356 800D[C56A0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3391 0000135D B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3392 0000135F E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3393 00001361 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3394                              <1> SND_LED1:
  3395 00001363 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3396 00001364 F605[C56A0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3397 0000136B 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3398                              <1> 	;
  3399 0000136D 800D[C56A0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3400                              <1> SL0:
  3401 00001374 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3402 00001376 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3403 0000137B FA                  <1> 	cli
  3404 0000137C E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3405 00001381 8025[C56A0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3406 00001388 0805[C56A0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3407 0000138E F605[C56A0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3408 00001395 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3409                              <1> 	;
  3410 00001397 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3411 0000139C FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3412 0000139D F605[C56A0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3413 000013A4 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3414                              <1> SL2:
  3415 000013A6 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3416 000013A8 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3417 000013AD FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3418                              <1> SL3:
  3419 000013AE 8025[C56A0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3420                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3421 000013B5 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3422 000013B6 C3                  <1> 	retn				; RETURN TO CALLER
  3423                              <1> 
  3424                              <1> MAKE_LED:
  3425                              <1> 	;---------------------------------------------------------------------------------
  3426                              <1> 	; MAKE_LED
  3427                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3428                              <1> 	;	THE MODE INDICATORS.
  3429                              <1> 	;---------------------------------------------------------------------------------
  3430                              <1> 	;
  3431                              <1> 	;push 	cx			; SAVE CX
  3432 000013B7 A0[C36A0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3433 000013BC 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3434                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3435                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3436 000013BE C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3437 000013C1 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3438                              <1> 	;pop	cx
  3439 000013C3 C3                  <1> 	retn				; RETURN TO CALLER
  3440                              <1> 
  3441                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3442                              <1> 
  3443                              <1> 
  3444                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1865                                  
  1866                                  %include 'video.s' ; 07/03/2015
  1867                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1868                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1869                              <1> ; ****************************************************************************
  1870                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1871                              <1> ; Last Modification: 27/02/2022
  1872                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1873                              <1> ;
  1874                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1875                              <1> 
  1876                              <1> ; 23/02/2022
  1877                              <1> ; 21/02/2022 (Retro UNIX 386 v1.2)
  1878                              <1> ; 07/02/2022 (Retro UNIX 386 V1&v1.1)
  1879                              <1> ; 02/02/2022 (simplified scroll up)
  1880                              <1> ; 16/01/2016
  1881                              <1> ; 30/06/2015
  1882                              <1> ; 27/06/2015
  1883                              <1> ; 11/03/2015
  1884                              <1> ; 02/09/2014
  1885                              <1> ; 30/08/2014
  1886                              <1> ; VIDEO FUNCTIONS
  1887                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1888                              <1> 
  1889                              <1> write_tty:
  1890                              <1> 	; 02/02/2022
  1891                              <1> 	; 13/08/2015
  1892                              <1> 	; 02/09/2014
  1893                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1894                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1895                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1896                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1897                              <1> 	;
  1898                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1899                              <1> 	;	   AL = Character to be written
  1900                              <1> 	;	   EBX = Video Page (0 to 7)
  1901                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1902                              <1> 
  1903                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1904                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1905                              <1> 
  1906                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1907                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1908                              <1> ;
  1909                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1910                              <1> ;
  1911                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1912                              <1> ;										:
  1913                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1914                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1915                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1916                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1917                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1918                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1919                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1920                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1921                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1922                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1923                              <1> ;   THE 0 COLOR IS USED.							:
  1924                              <1> ;   ENTRY --									:
  1925                              <1> ;     (AH) = CURRENT CRT MODE							:
  1926                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1927                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1928                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1929                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1930                              <1> ;   EXIT -- 									:
  1931                              <1> ;     ALL REGISTERS SAVED							:
  1932                              <1> ;--------------------------------------------------------------------------------
  1933                              <1> 
  1934 000013C4 FA                  <1> 	cli
  1935                              <1> 	;
  1936                              <1> 	; READ CURSOR (04/12/2013)
  1937                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1938 000013C5 08FF                <1> 	or	bh, bh
  1939                              <1> 	;jnz	beeper
  1940                              <1> 	; 02/02/2022
  1941 000013C7 7405                <1> 	jz	short u14
  1942 000013C9 E992000000          <1> 	jmp	beeper
  1943                              <1> u14:
  1944                              <1> 	; 02/02/2022
  1945                              <1> 	;; 01/09/2014
  1946                              <1> 	;cmp	byte [CRT_MODE], 3
  1947                              <1> 	;je	short m3
  1948                              <1> 	;;
  1949                              <1> 	;call	set_mode
  1950                              <1> m3:
  1951 000013CE 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1952                              <1> 	;shl	si, 1
  1953                              <1> 	; 02/02/2022
  1954 000013D0 D1E6                <1> 	shl	esi, 1
  1955 000013D2 81C6[B6700000]      <1> 	add	esi, cursor_posn
  1956 000013D8 668B16              <1> 	mov	dx, [esi]
  1957                              <1> 	;
  1958                              <1> 	; dx now has the current cursor position
  1959                              <1> 	;
  1960 000013DB 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1961 000013DD 7647                <1> 	jbe	short u8
  1962                              <1> 	;
  1963                              <1> 	; write the char to the screen
  1964                              <1> u0:	
  1965                              <1> 	; ah = attribute/color
  1966                              <1> 	; al = character
  1967                              <1> 	; bl = video page number (0 to 7)
  1968                              <1> 	; bh = 0
  1969                              <1> 	;
  1970 000013DF E8D6010000          <1> 	call	write_c_current
  1971                              <1> 	;
  1972                              <1> 	; position the cursor for next char
  1973 000013E4 FEC2                <1> 	inc	dl		; next column
  1974                              <1> 	;cmp	dl, [CRT_COLS]
  1975 000013E6 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1976                              <1>         ;jne	set_cpos
  1977                              <1> 	; 02/02/2022
  1978 000013E9 7405                <1> 	je	short u13
  1979 000013EB E9DE000000          <1> 	jmp	set_cpos
  1980                              <1> u13:
  1981 000013F0 B200                <1> 	mov	dl, 0		; column = 0
  1982                              <1> u10:				; (line feed found)
  1983 000013F2 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1984 000013F5 7228                <1> 	jb 	short u6
  1985                              <1> 	;
  1986                              <1> 	; scroll required
  1987                              <1> u1:	
  1988                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1989 000013F7 E8D2000000          <1> 	call	set_cpos
  1990                              <1> 	;
  1991                              <1> 	; determine value to fill with during scroll
  1992                              <1> u2:
  1993                              <1> 	; READ_AC_CURRENT		:
  1994                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1995                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1996                              <1> 	;
  1997                              <1> 	; INPUT				
  1998                              <1> 	;	(AH) = CURRENT CRT MODE
  1999                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2000                              <1> 	;	(DS) = DATA SEGMENT
  2001                              <1> 	;	(ES) = REGEN SEGMENT
  2002                              <1> 	; OUTPUT			
  2003                              <1> 	;	(AL) = CHARACTER READ
  2004                              <1> 	;	(AH) = ATTRIBUTE READ
  2005                              <1> 	;
  2006                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2007                              <1> 	;
  2008                              <1> 	; bl = video page number
  2009                              <1> 	;
  2010 000013FC E82D010000          <1> 	call	find_position	; get regen location and port address
  2011                              <1> 	; dx = status port
  2012                              <1> 	; esi = cursor location/address
  2013                              <1> p11:
  2014 00001401 FB                  <1> 	sti			; enable interrupts
  2015 00001402 90                  <1> 	nop			; allow for small interupts window
  2016 00001403 FA                  <1> 	cli			; blocks interrupts for single loop
  2017 00001404 EC                  <1> 	in	al, dx		; get status from adapter
  2018 00001405 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2019 00001407 75F8                <1> 	jnz	short p11	; wait until it is
  2020                              <1> p12:				; now wait for either retrace high
  2021 00001409 EC                  <1> 	in	al, dx		; get status
  2022 0000140A A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2023 0000140C 74FB                <1> 	jz	short p12	; wait until either is active	
  2024                              <1> p13:
  2025 0000140E 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2026 00001414 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2027                              <1> 	;
  2028                              <1> 	; al = character, ah = attribute
  2029                              <1> 	;
  2030 00001417 FB                  <1> 	sti
  2031                              <1> 	; bl = video page number 	
  2032                              <1> u3:
  2033                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2034                              <1> 	;;sub	cx, cx		; upper left corner
  2035                              <1> 	;;mov	dh, 25-1 	; lower right row
  2036                              <1> 	;;;mov	dl, [CRT_COLS]
  2037                              <1> 	;mov	dl, 80		; lower right column	
  2038                              <1> 	;;dec	dl
  2039                              <1> 	;;mov	dl, 79
  2040                              <1> 
  2041                              <1> 	;;call	scroll_up	; 04/12/2013
  2042                              <1> 	;;; 11/03/2015
  2043                              <1> 	; 02/09/2014
  2044                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2045                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2046                              <1> 	; 11/03/2015
  2047                              <1> 	;sub	cx, cx
  2048                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2049                              <1> 	;
  2050                              <1> 	; 02/02/2022 (simplied scroll up)
  2051                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2052                              <1> 	;
  2053 00001418 B001                <1> 	mov	al, 1		; scroll 1 line up
  2054                              <1> 		; ah = attribute
  2055 0000141A E939010000          <1> 	jmp	scroll_up
  2056                              <1> ;u4:
  2057                              <1> 	;;int	10h		; video-call return
  2058                              <1> 				; scroll up the screen
  2059                              <1> 				; tty return
  2060                              <1> ;u5:
  2061                              <1> 	;retn			; return to the caller
  2062                              <1> 
  2063                              <1> u6:				; set-cursor-inc
  2064 0000141F FEC6                <1> 	inc	dh		; next row
  2065                              <1> 				; set cursor
  2066                              <1> ;u7:					
  2067                              <1> 	;;mov	ah, 02h
  2068                              <1> 	;;jmp	short u4 	; establish the new cursor
  2069                              <1> 	;call	set_cpos
  2070                              <1> 	;jmp 	short u5
  2071 00001421 E9A8000000          <1> 	jmp     set_cpos
  2072                              <1> 
  2073                              <1> 	; check for control characters
  2074                              <1> u8:
  2075 00001426 7434                <1> 	je	short u9
  2076 00001428 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2077 0000142A 74C6                <1> 	je	short u10
  2078 0000142C 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2079 0000142E 7430                <1> 	je	short u11
  2080 00001430 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2081                              <1> 	;jne	short u0
  2082 00001432 7420                <1> 	je	short bs	; 12/12/2013
  2083                              <1> 	; 12/12/2013 (tab stop)
  2084 00001434 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2085 00001436 75A7                <1> 	jne	short u0
  2086 00001438 88D0                <1> 	mov	al, dl
  2087 0000143A 6698                <1> 	cbw
  2088 0000143C B108                <1> 	mov	cl, 8
  2089 0000143E F6F1                <1> 	div	cl
  2090 00001440 28E1                <1> 	sub	cl, ah
  2091                              <1> ts:
  2092                              <1> 	; 02/09/2014
  2093                              <1> 	; 01/09/2014
  2094 00001442 B020                <1> 	mov	al, 20h
  2095                              <1> tsloop:
  2096                              <1> 	;push	cx
  2097                              <1> 	;push	ax
  2098                              <1> 	; 02/02/2022
  2099 00001444 51                  <1> 	push	ecx
  2100 00001445 50                  <1> 	push	eax
  2101 00001446 30FF                <1> 	xor 	bh, bh
  2102                              <1> 	;mov	bl, [active_page]
  2103 00001448 E881FFFFFF          <1> 	call	m3
  2104                              <1> 	; 02/02/2022
  2105 0000144D 58                  <1> 	pop	eax
  2106 0000144E 59                  <1>  	pop	ecx
  2107                              <1> 	;pop	ax  ; ah = attribute/color
  2108                              <1> 	;pop	cx
  2109 0000144F FEC9                <1> 	dec	cl
  2110 00001451 75F1                <1> 	jnz	short tsloop
  2111 00001453 C3                  <1> 	retn
  2112                              <1> bs:	
  2113                              <1> 	; back space found
  2114 00001454 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2115                              <1> 	;je	short u7 	; set_cursor
  2116 00001456 7476                <1> 	jz	short set_cpos
  2117                              <1> 	;dec	dx     		; no -- just move it back
  2118                              <1> 	; 02/02/2022
  2119 00001458 FECA                <1> 	dec	dl
  2120                              <1> 	;jmp	short u7
  2121 0000145A EB72                <1> 	jmp	short set_cpos
  2122                              <1> 
  2123                              <1> 	; carriage return found
  2124                              <1> u9:
  2125 0000145C B200                <1> 	mov	dl, 0 		; move to first column
  2126                              <1> 	;jmp	short u7
  2127 0000145E EB6E                <1> 	jmp	short set_cpos
  2128                              <1> 
  2129                              <1> 	; line feed found
  2130                              <1> ;u10:
  2131                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2132                              <1> ;	jne	short u6 	; no, just set the cursor
  2133                              <1> ;       jmp     u1              ; yes, scroll the screen
  2134                              <1> 
  2135                              <1> beeper: 
  2136                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2137                              <1> 	; 18/01/2014
  2138                              <1> 	; 03/12/2013
  2139                              <1> 	; bell found
  2140                              <1> u11:
  2141 00001460 FB                  <1> 	sti
  2142 00001461 3A1D[C6700000]      <1> 	cmp	bl, [active_page]
  2143 00001467 7551                <1> 	jne	short u12	; Do not sound the beep 
  2144                              <1> 				; if it is not written on the active page
  2145 00001469 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2146 0000146D B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2147                              <1> 	;call	beep		; sound the pod bell
  2148                              <1> 	;jmp	short u5 	; tty_return
  2149                              <1> 	;retn
  2150                              <1> 	
  2151                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2152                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2153                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2154                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2155                              <1> 
  2156                              <1> beep:
  2157                              <1> 	; 07/02/2015
  2158                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2159                              <1> 	; 18/01/2014
  2160                              <1> 	; 03/12/2013
  2161                              <1> 	;
  2162                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2163                              <1> 	;
  2164                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2165                              <1> 	;
  2166                              <1> 	; ENTRY:
  2167                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2168                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2169                              <1> 	; EXIT:			:
  2170                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2171                              <1> 
  2172 0000146F 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2173 00001470 FA                  <1> 	cli			; block interrupts during update
  2174 00001471 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2175 00001473 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2176 00001475 EB00                <1> 	jmp	$+2		; I/O delay
  2177 00001477 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2178 00001479 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2179 0000147B EB00                <1> 	jmp	$+2		; I/O delay
  2180 0000147D 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2181 0000147F E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2182 00001481 E461                <1> 	in	al, PORT_B	; get current setting of port
  2183 00001483 88C4                <1> 	mov	ah, al		; save that setting
  2184 00001485 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2185 00001487 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2186                              <1> 	;popf	; 18/01/2014
  2187 00001489 FB                  <1> 	sti
  2188                              <1> g7:				; 1/64 second per count (bl)
  2189 0000148A B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2190 0000148F E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2191 00001494 FECB                <1> 	dec	bl		; (bl) length count expired?
  2192 00001496 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2193                              <1> 	;
  2194                              <1> 	;pushf			; save interrupt status
  2195 00001498 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2196 00001499 E461                <1> 	in	al, PORT_B	; get current port value
  2197                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2198 0000149B 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2199 0000149D 20C4                <1>         and	ah, al		; someone turned them off during beep
  2200 0000149F 88E0                <1> 	mov	al, ah		; recover value of port
  2201                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2202 000014A1 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2203 000014A3 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2204                              <1> 	;popf			; restore interrupt flag state
  2205 000014A5 FB                  <1> 	sti
  2206 000014A6 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2207 000014AB E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2208                              <1> 	;pushf			; save interrupt status
  2209 000014B0 FA                  <1> 	cli			; block interrupts during update
  2210 000014B1 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2211 000014B3 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2212 000014B5 08E0                <1> 	or	al, ah		; recover value of port_b
  2213 000014B7 E661                <1> 	out	PORT_B, al	; restore speaker status
  2214 000014B9 9D                  <1> 	popf			; restore interrupt flag state
  2215                              <1> u12:	
  2216 000014BA C3                  <1> 	retn
  2217                              <1> 
  2218                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2219                              <1> 
  2220                              <1> WAITF:
  2221                              <1> waitf:
  2222                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2223                              <1> 	; 03/12/2013
  2224                              <1> 	;
  2225                              <1> ;	push	ax		; save work register (ah)	
  2226                              <1> ;waitf1:
  2227                              <1> 				; use timer 1 output bits
  2228                              <1> ;	in	al, PORT_B	; read current counter output status
  2229                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2230                              <1> ;	cmp	al, ah		; did it just change
  2231                              <1> ;	je	short waitf1	; wait for a change in output line
  2232                              <1> ;	;
  2233                              <1> ;	mov	ah, al		; save new lflag state
  2234                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2235                              <1> ;	;
  2236                              <1> ;	pop	ax		; restore (ah)
  2237                              <1> ;	retn			; return (cx)=0
  2238                              <1> 
  2239                              <1> ; 02/02/2022
  2240                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2241                              <1> ; 17/12/2014 (dsectrm2.s)
  2242                              <1> ; WAITF
  2243                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2244                              <1> ;
  2245                              <1> ;---WAITF-----------------------------------------------------------------------
  2246                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2247                              <1> ; ENTRY:
  2248                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2249                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2250                              <1> ; EXIT:
  2251                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2252                              <1> ;	(CX) = 0	
  2253                              <1> ;-------------------------------------------------------------------------------
  2254                              <1> 
  2255                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2256                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2257                              <1> 
  2258                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2259 000014BB 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2260                              <1> 	;push	ax
  2261                              <1> 	; 16/12/2014
  2262                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2263 000014BC D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2264                              <1> ;17/12/2014	
  2265                              <1> ;WAITF1:
  2266                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2267                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2268                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2269                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2270                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2271                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2272                              <1> 	;
  2273                              <1> 	; 17/12/2014
  2274                              <1> 	;
  2275                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2276                              <1> 	;
  2277                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2278                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2279                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2280                              <1> WR_STATE_0:
  2281 000014BE E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2282 000014C0 A810                <1> 	TEST	AL,010H
  2283 000014C2 74FA                <1> 	JZ	SHORT WR_STATE_0
  2284                              <1> WR_STATE_1:
  2285 000014C4 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2286 000014C6 A810                <1> 	TEST	AL,010H
  2287 000014C8 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2288 000014CA E2F2                <1>         LOOP    WR_STATE_0
  2289                              <1> 	;
  2290                              <1> 	;pop	ax
  2291 000014CC 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2292 000014CD C3                  <1> 	RETn				; (CX) = 0
  2293                              <1> 
  2294                              <1> set_cpos:
  2295                              <1> 	; 27/02/2022
  2296                              <1> 	; 23/02/2022
  2297                              <1> 	; 02/02/2022
  2298                              <1> 	; 27/06/2015
  2299                              <1> 	; 01/09/2014
  2300                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2301                              <1> 	;
  2302                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2303                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2304                              <1> 	;
  2305                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2306                              <1> 	;
  2307                              <1> 	; SET_CPOS
  2308                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2309                              <1> 	;	NEW X-Y VALUES PASSED
  2310                              <1> 	; INPUT
  2311                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2312                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2313                              <1> 	; OUTPUT
  2314                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2315                              <1> 	;
  2316 000014CE 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2317 000014D1 D0E0                <1>         shl     al, 1   ; word offset
  2318 000014D3 BE[B6700000]        <1> 	mov	esi, cursor_posn
  2319 000014D8 01C6                <1>         add     esi, eax
  2320 000014DA 668916              <1> 	mov	[esi], dx ; save the pointer
  2321 000014DD 381D[C6700000]      <1> 	cmp	[active_page], bl
  2322 000014E3 7536                <1> 	jne	short m17
  2323                              <1> 
  2324 000014E5 FA                  <1> 	cli	; 27/02/2022
  2325                              <1> 
  2326                              <1> 	;call	m18	; CURSOR SET
  2327                              <1> ;m17:			; SET_CPOS_RETURN
  2328                              <1> 	; 01/09/2014
  2329                              <1> ;	retn
  2330                              <1> 		; DX = row/column
  2331                              <1> m18:
  2332 000014E6 E835000000          <1> 	call	position ; determine location in regen buffer	
  2333                              <1> 	;mov	cx, [CRT_START]
  2334                              <1> 	; 23/02/2022
  2335 000014EB 0FB70D[B4700000]    <1> 	movzx	ecx, word [CRT_START]
  2336 000014F2 01C1                <1> 	add	ecx, eax
  2337                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2338                              <1> 			; to the start address (offset) for this page
  2339                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2340                              <1> 	; 23/02/2022
  2341 000014F4 D1E9                <1> 	shr	ecx, 1
  2342 000014F6 B40E                <1> 	mov	ah, 14	; register number for cursor
  2343                              <1> 	
  2344 000014F8 E802000000          <1> 	call	m16	; output value to the 6845
  2345 000014FD FB                  <1> 	sti	; 27/02/2022
  2346 000014FE C3                  <1> 	retn
  2347                              <1> 
  2348                              <1> 	; 27/02/2022
  2349                              <1> 	; 02/02/2022
  2350                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2351                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2352                              <1> m16:
  2353                              <1> 	;cli	; 27/02/2022
  2354                              <1> 	;mov	dx, [addr_6845] ; address register
  2355 000014FF 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2356 00001503 88E0                <1> 	mov	al, ah	; get value
  2357 00001505 EE                  <1> 	out	dx, al	; register set
  2358                              <1> 	;inc	dx	; data register
  2359                              <1> 	; 02/02/2022
  2360 00001506 FEC2                <1> 	inc	dl
  2361 00001508 EB00                <1> 	jmp	$+2	; i/o delay
  2362 0000150A 88E8                <1> 	mov	al, ch	; data
  2363 0000150C EE                  <1> 	out	dx, al	
  2364                              <1> 	;dec	dx
  2365                              <1> 	; 02/02/2022	
  2366 0000150D FECA                <1> 	dec	dl
  2367 0000150F 88E0                <1> 	mov	al, ah
  2368 00001511 FEC0                <1> 	inc	al	; point to other data register
  2369 00001513 EE                  <1> 	out	dx, al	; set for second register
  2370                              <1> 	;inc	dx
  2371                              <1> 	; 02/02/2022
  2372 00001514 FEC2                <1> 	inc	dl
  2373 00001516 EB00                <1> 	jmp	$+2	; i/o delay
  2374 00001518 88C8                <1> 	mov	al, cl	; second data value
  2375 0000151A EE                  <1> 	out	dx, al
  2376                              <1> 	;sti	; 27/02/2022
  2377                              <1> m17:
  2378 0000151B C3                  <1> 	retn
  2379                              <1> 
  2380                              <1> set_ctype:
  2381                              <1> 	; 07/02/2022
  2382                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2383                              <1> 	;
  2384                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2385                              <1> 
  2386                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2387                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2388                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2389                              <1> ;          OR NO CURSOR AT ALL
  2390                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2391                              <1> 
  2392                              <1> ;------------------------------------------------
  2393                              <1> ; SET_CTYPE
  2394                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2395                              <1> ; INPUT
  2396                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2397                              <1> ; OUTPUT	
  2398                              <1> ;	NONE
  2399                              <1> ;------------------------------------------------
  2400                              <1> 
  2401 0000151C B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2402                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2403                              <1> 	;call	m16	; output cx register
  2404                              <1> 	;retn
  2405                              <1> 	; 07/02/2022
  2406 0000151E EBDF                <1> 	jmp	short m16
  2407                              <1> 
  2408                              <1> position:
  2409                              <1> 	; 23/02/2022
  2410                              <1> 	; 02/02/2022
  2411                              <1> 	; 27/06/2015
  2412                              <1> 	; 02/09/2014
  2413                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2414                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2415                              <1> 	;
  2416                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2417                              <1> 	;
  2418                              <1> 	; POSITION
  2419                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2420                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2421                              <1> 	; INPUT
  2422                              <1> 	;	AX = ROW, COLUMN POSITION
  2423                              <1> 	; OUTPUT
  2424                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2425                              <1> 
  2426                              <1> 		; DX = ROW, COLUMN POSITION
  2427                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2428 00001520 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2429 00001522 B050                <1> 	mov	al, 80	; determine bytes to row	
  2430 00001524 F6E6                <1> 	mul	dh	; row value
  2431                              <1> 	;xor	dh, dh	; 0
  2432                              <1> 	;add	ax, dx	; add column value to the result
  2433                              <1> 	; 23/02/2022
  2434 00001526 00D0                <1> 	add	al, dl
  2435 00001528 80D400              <1> 	adc	ah, 0	
  2436                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2437                              <1> 	; 02/02/2022
  2438 0000152B D1E0                <1> 	shl	eax, 1
  2439                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2440 0000152D C3                  <1> 	retn
  2441                              <1> 
  2442                              <1> find_position:
  2443                              <1> 	; 02/02/2022
  2444                              <1> 	; 27/06/2015
  2445                              <1> 	; 07/09/2014
  2446                              <1> 	; 02/09/2014
  2447                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2448                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2449 0000152E 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2450 00001531 89CE                <1> 	mov	esi, ecx
  2451                              <1> 	;shl	si, 1
  2452                              <1> 	; 02/02/2022
  2453 00001533 D1E6                <1> 	shl	esi, 1
  2454 00001535 668B96[B6700000]    <1> 	mov	dx, [esi+cursor_posn]
  2455 0000153C 7409                <1> 	jz	short p21
  2456                              <1> 	;xor	si, si
  2457                              <1> 	; 02/02/2022
  2458 0000153E 31F6                <1> 	xor	esi, esi
  2459                              <1> p20:
  2460                              <1> 	;add	si, [CRT_LEN]
  2461 00001540 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2462 00001545 E2F9                <1> 	loop	p20
  2463                              <1> p21:
  2464 00001547 6621D2              <1> 	and	dx, dx
  2465 0000154A 7407                <1> 	jz	short p22
  2466 0000154C E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2467 00001551 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2468                              <1> p22:	
  2469                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2470                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2471                              <1> 	;add	dx, 6	; point at status port
  2472 00001553 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2473                              <1> 	; cx = 0
  2474 00001557 C3                  <1> 	retn
  2475                              <1> 
  2476                              <1> scroll_up:
  2477                              <1> 	; 02/02/2022 (simplified scroll up)
  2478                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2479                              <1> 	; 16/01/2016
  2480                              <1> 	; 07/09/2014
  2481                              <1> 	; 02/09/2014
  2482                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2483                              <1> 	; 04/04/2014
  2484                              <1> 	; 04/12/2013
  2485                              <1> 	;
  2486                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2487                              <1> 	;
  2488                              <1> 	; SCROLL UP
  2489                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2490                              <1> 	;	ON THE SCREEN
  2491                              <1> 	; INPUT
  2492                              <1> 	;	(AH) = CURRENT CRT MODE
  2493                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2494                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2495                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2496                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2497                              <1> 	;	(DS) = DATA SEGMENT
  2498                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2499                              <1> 	; OUTPUT
  2500                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2501                              <1> 	;
  2502                              <1> 	;	bh = 0  (02/09/2014)
  2503                              <1> 	;
  2504                              <1> 	; ((ah = 3))
  2505                              <1> 	; cl = left upper column
  2506                              <1> 	; ch = left upper row
  2507                              <1> 	; dl = right lower column
  2508                              <1> 	; dh = right lower row
  2509                              <1> 	;
  2510                              <1> 	; al = line count 
  2511                              <1> 	; ah = attribute to be used on blanked line
  2512                              <1> 	; bl = video page number (0 to 7)
  2513                              <1> 	; 
  2514                              <1> 
  2515                              <1> 	; 02/02/2022 'scroll_up' code
  2516                              <1> 	; ------------------------------------------------------
  2517                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2518                              <1> 
  2519                              <1> 	; INPUT:
  2520                              <1> 	;		
  2521                              <1> 	; al = line count 
  2522                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2523                              <1> 	; ah = attribute to be used on blanked line
  2524                              <1> 	; bl = video page number (0 to 7)
  2525                              <1> 
  2526                              <1> 	;cli
  2527 00001558 31C9                <1> 	xor	ecx, ecx
  2528 0000155A 88C1                <1> 	mov	cl, al ; line count (cl)
  2529 0000155C BE00800B00          <1> 	mov	esi, 0B8000h
  2530 00001561 3A1D[C6700000]      <1> 	cmp	bl, [active_page]
  2531 00001567 7411                <1> 	je	short n1
  2532 00001569 20DB                <1> 	and	bl, bl
  2533 0000156B 7422                <1> 	jz	short n3
  2534 0000156D 88DD                <1> 	mov	ch, bl ; video page number
  2535                              <1> n0:
  2536 0000156F 6681C6A00F          <1> 	add	si, 25*80*2
  2537 00001574 FECD                <1> 	dec	ch
  2538 00001576 75F7                <1> 	jnz	short n0
  2539 00001578 EB15                <1> 	jmp	short n3
  2540                              <1> n1:
  2541 0000157A 660335[B4700000]    <1> 	add	si, [CRT_START]
  2542                              <1> 	;
  2543 00001581 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2544                              <1> n2:			 ; wait_display_enable
  2545 00001585 EC                  <1> 	in	al, dx	 ; get port
  2546 00001586 A808                <1> 	test	al, RVRT ; wait for vertical retrace
  2547 00001588 74FB                <1> 	jz	short n2 ; wait_display_enable
  2548 0000158A B025                <1> 	mov	al, 25h
  2549 0000158C B2D8                <1> 	mov	dl, 0D8h ; address control port
  2550 0000158E EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2551                              <1> n3:
  2552                              <1> 	; cl = line count
  2553                              <1> 	; ah = attribute/color
  2554 0000158F 89F7                <1> 	mov	edi, esi
  2555 00001591 20C9                <1> 	and	cl, cl
  2556 00001593 741F                <1> 	jz	short n6
  2557 00001595 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2558 0000159A 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2559 0000159E F366A5              <1> 	rep	movsw
  2560 000015A1 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2561                              <1> n4:
  2562                              <1> 	; ah = character attribute/cocor
  2563 000015A3 B020                <1> 	mov	al, 20h ; fill with blanks
  2564 000015A5 F366AB              <1> 	rep	stosw
  2565                              <1> 
  2566 000015A8 3A1D[C6700000]      <1> 	cmp	bl, [active_page]
  2567 000015AE 7503                <1> 	jne	short n5
  2568                              <1> 
  2569                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2570 000015B0 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2571                              <1> 	;mov	dx, 03D8h ; always set color card port
  2572 000015B2 EE                  <1> 	out	dx, al
  2573                              <1> n5:
  2574 000015B3 C3                  <1> 	retn
  2575                              <1> n6:
  2576                              <1> 	; clear video page
  2577 000015B4 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2578 000015B8 EBE9                <1> 	jmp	short n4
  2579                              <1> 
  2580                              <1> 	; 23/02/2022
  2581                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2582                              <1> 	; ------------------------------------------------------
  2583                              <1> 
  2584                              <1> 	; Test	Line Count
  2585                              <1> 	or	al, al
  2586                              <1> 	jz	short al_set
  2587                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2588                              <1> 	sub	bh, ch
  2589                              <1> 	inc	bh	; adjust difference by 1
  2590                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2591                              <1> 	jne	short al_set ; if not the we're all set
  2592                              <1> 	xor	al, al	; otherwise set al to zero
  2593                              <1> al_set:
  2594                              <1> 	xor	bh, bh	; 0
  2595                              <1> 	;push	ax
  2596                              <1> 	push	eax ; 23/02/2022
  2597                              <1> 	;mov 	esi, [crt_base]
  2598                              <1>         mov     esi, 0B8000h  
  2599                              <1>         cmp     bl, [active_page]
  2600                              <1> 	jne	short n0
  2601                              <1> 	;
  2602                              <1>         mov     ax, [CRT_START]
  2603                              <1>         add     si, ax
  2604                              <1>         jmp     short n1
  2605                              <1> n0:
  2606                              <1>         and     bl, bl
  2607                              <1> 	jz	short n1
  2608                              <1> 	mov	al, bl
  2609                              <1> n0x:
  2610                              <1>         ;add    si, [CRT_LEN]
  2611                              <1>         ;add    esi, 80*25*2 
  2612                              <1>         add     si, 80*25*2
  2613                              <1>         dec	al
  2614                              <1> 	jnz	short n0x
  2615                              <1> n1:	
  2616                              <1>         ; Scroll position
  2617                              <1> 	;push	dx ; 23/02/2022
  2618                              <1> 	mov	dx, cx	; now, upper left position in DX
  2619                              <1> 	call	position
  2620                              <1> 	add	esi, eax
  2621                              <1> 	mov	edi, esi
  2622                              <1> 	;pop	dx	; lower right position in DX
  2623                              <1> 	sub	dx, cx
  2624                              <1> 	inc	dh	; dh = #rows 
  2625                              <1> 	inc	dl	; dl = #cols in block
  2626                              <1> 	;pop	ax	; al = line count, ah = attribute
  2627                              <1> 	pop	eax ; 23/02/2022
  2628                              <1> 	xor	ecx, ecx
  2629                              <1> 	mov	cx, ax
  2630                              <1> 	;mov	ah, [CRT_COLS]
  2631                              <1> 	mov	ah, 80
  2632                              <1> 	mul	ah	; determine offset to from address
  2633                              <1> 	add	ax, ax  ; *2 for attribute byte
  2634                              <1> 	;
  2635                              <1> 	;push	ax	; offset 
  2636                              <1> 	;push	dx
  2637                              <1> 	; 23/02/2022
  2638                              <1> 	push	eax
  2639                              <1> 	push	edx
  2640                              <1> 	;
  2641                              <1> 	; 04/04/2014
  2642                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2643                              <1> n8:                      ; wait_display_enable
  2644                              <1>         in      al, dx   ; get port
  2645                              <1> 	test	al, RVRT ; wait for vertical retrace
  2646                              <1> 	jz	short n8 ; wait_display_enable
  2647                              <1> 	mov	al, 25h
  2648                              <1> 	mov	dl, 0D8h ; address control port
  2649                              <1> 	out	dx, al	; turn off video during vertical retrace
  2650                              <1> 	;pop	dx	; #rows, #cols
  2651                              <1>        	;pop	ax	; offset
  2652                              <1> 	; 23/02/2022
  2653                              <1> 	pop	edx
  2654                              <1> 	pop	eax
  2655                              <1> 	xchg	ax, cx	; 
  2656                              <1> 	; ecx = offset, al = line count, ah = attribute
  2657                              <1> ;n9:
  2658                              <1> 	or	al, al
  2659                              <1>         jz      short n3 
  2660                              <1>         add     esi, ecx ; from address for scroll
  2661                              <1> 	mov	bh, dh  ; #rows in block
  2662                              <1> 	sub	bh, al	; #rows to be moved
  2663                              <1> n2:
  2664                              <1> 	; Move rows
  2665                              <1> 	mov	cl, dl	; get # of cols to move
  2666                              <1> 	push	esi
  2667                              <1> 	push	edi	; save start address
  2668                              <1> n10:
  2669                              <1> 	movsw		; move that line on screen
  2670                              <1> 	dec	cl
  2671                              <1>         jnz     short n10
  2672                              <1> 	pop	edi
  2673                              <1> 	pop	esi	; recover addresses
  2674                              <1>         ;mov    cl, [CRT_COLS] 
  2675                              <1> 	;add	cl, cl
  2676                              <1>         ;mov    ecx, 80*2
  2677                              <1>         mov     cx, 80*2
  2678                              <1>         add     esi, ecx  ; next line
  2679                              <1>         add     edi, ecx
  2680                              <1> 	dec	bh	 ; count of lines to move
  2681                              <1> 	jnz	short n2 ; row loop
  2682                              <1> 	; bh = 0
  2683                              <1> 	mov	dh, al	 ; #rows	
  2684                              <1> n3:
  2685                              <1> 	; attribute in ah
  2686                              <1> 	mov	al, ' '	 ; fill with blanks
  2687                              <1> n3x:
  2688                              <1> 	; Clear rows
  2689                              <1>                 ; dh =  #rows
  2690                              <1>         mov	cl, dl	; get # of cols to clear
  2691                              <1>         push    edi     ; save address
  2692                              <1> n11:
  2693                              <1>         stosw           ; store fill character
  2694                              <1> 	dec	cl
  2695                              <1>         jnz     short n11
  2696                              <1>         pop     edi     ; recover address
  2697                              <1> 	;mov	cl, [CRT_COLS]
  2698                              <1> 	;add	cl, cl
  2699                              <1>         ;mov    ecx, 80*2
  2700                              <1>         mov	cl, 80*2
  2701                              <1>         add     edi, ecx
  2702                              <1> 	dec	dh
  2703                              <1> 	jnz	short n3x ; 16/01/2016
  2704                              <1> 	;
  2705                              <1> 	cmp	bl, [active_page]
  2706                              <1> 	jne	short n6
  2707                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2708                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2709                              <1> 	mov	dx, 03D8h ; always set color card port
  2710                              <1> 	out	dx, al
  2711                              <1> n6:
  2712                              <1> 	retn
  2713                              <1> 
  2714                              <1> %endif
  2715                              <1> 
  2716                              <1> write_c_current:
  2717                              <1> 	; 02/02/2022
  2718                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2719                              <1> 	; 18/01/2014
  2720                              <1> 	; 04/12/2013
  2721                              <1> 	;
  2722                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2723                              <1> 	;
  2724                              <1> 	; WRITE_C_CURRENT
  2725                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2726                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2727                              <1> 	; INPUT	
  2728                              <1> 	;	(AH) = CURRENT CRT MODE
  2729                              <1> 	;	(BH) = DISPLAY PAGE
  2730                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2731                              <1> 	;	(AL) = CHAR TO WRITE
  2732                              <1> 	;	(DS) = DATA SEGMENT
  2733                              <1> 	;	(ES) = REGEN SEGMENT
  2734                              <1> 	; OUTPUT
  2735                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2736                              <1> 
  2737 000015BA FA                  <1> 	cli		
  2738                              <1> 	; bl = video page
  2739                              <1> 	; al = character
  2740                              <1> 	; ah = color/attribute
  2741                              <1> 	;push	dx
  2742                              <1> 	;push	ax	; save character & attribute/color
  2743                              <1> 	; 02/02/2022
  2744 000015BB 52                  <1> 	push	edx
  2745 000015BC 50                  <1> 	push	eax
  2746 000015BD E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2747                              <1> 	; esi = regen location
  2748                              <1> 	; dx = status port
  2749                              <1> 	;
  2750                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2751                              <1> 	;
  2752                              <1> p41:			; wait for horizontal retrace is low or vertical
  2753 000015C2 FB                  <1> 	sti		; enable interrupts first
  2754 000015C3 3A1D[C6700000]      <1>         cmp     bl, [active_page]
  2755 000015C9 7510                <1> 	jne	short p44 
  2756 000015CB FA                  <1> 	cli 		; block interrupts for single loop
  2757 000015CC EC                  <1> 	in	al, dx	; get status from the adapter
  2758 000015CD A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2759 000015CF 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2760 000015D1 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2761 000015D3 75ED                <1> 	jnz	short p41 ; wait until it is
  2762                              <1> p42:			; wait for either retrace high
  2763 000015D5 EC                  <1> 	in	al, dx	; get status again
  2764 000015D6 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2765 000015D8 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2766                              <1> p43:	
  2767 000015DA FB                  <1> 	sti
  2768                              <1> p44:
  2769                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2770                              <1> 	; 02/02/2022
  2771 000015DB 58                  <1> 	pop	eax
  2772 000015DC 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2773                              <1> 			; Retro UNIX 386 v1 feature only!
  2774 000015E2 668906              <1> 	mov	[esi], ax
  2775                              <1> 	;pop	dx
  2776                              <1> 	; 02/02/2022
  2777 000015E5 5A                  <1> 	pop	edx
  2778 000015E6 C3                  <1> 	retn
  2779                              <1> 
  2780                              <1> %if 0	; 02/02/2022
  2781                              <1> 
  2782                              <1> set_mode:
  2783                              <1> 	; 02/02/2022
  2784                              <1> 	; 16/01/2016
  2785                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2786                              <1> 	;
  2787                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2788                              <1> 
  2789                              <1> ;------------------------------------------------------
  2790                              <1> ; SET MODE					      :
  2791                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2792                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2793                              <1> ; INPUT						      :
  2794                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2795                              <1> ; OUTPUT					      :
  2796                              <1> ;	NONE					      :
  2797                              <1> ;------------------------------------------------------
  2798                              <1> 
  2799                              <1> 	push	edi ; 16/01/2016
  2800                              <1> 	push	ebx
  2801                              <1> 	push	edx
  2802                              <1> 	push	ecx ; 16/01/2016
  2803                              <1>         push    eax
  2804                              <1> 
  2805                              <1> 	;mov	dx, 03D4h 	; address or color card
  2806                              <1> 	mov	al, 3
  2807                              <1> ;M8:
  2808                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2809                              <1> 	mov	al, 29h
  2810                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2811                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2812                              <1> 	;push	dx  		; save port value
  2813                              <1> 	;add	dx, 4		; point to control register
  2814                              <1> 	mov	dx, 3D8h
  2815                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2816                              <1> 	;pop	dx
  2817                              <1> ;M9:
  2818                              <1> 	mov	ebx, video_params ; initialization table
  2819                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2820                              <1> 	;xchg 	ah, al
  2821                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2822                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2823                              <1> 	
  2824                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2825                              <1> 	; 02/02/2022
  2826                              <1> 	; dx = 3D8h
  2827                              <1> 	xor	ecx, ecx
  2828                              <1> 	mov	cl, 16
  2829                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2830                              <1> M10:			;  initialization loop
  2831                              <1> 	mov	al, ah 	; get 6845 register number
  2832                              <1> 	out	dx, al
  2833                              <1> 	;inc	dx      ; point to data port
  2834                              <1> 	; 02/02/2022
  2835                              <1> 	inc	dl ; 3D9h
  2836                              <1> 	inc	ah	; next register value
  2837                              <1> 	mov	al, [ebx] ; get table value
  2838                              <1> 	out	dx, al	; out to chip
  2839                              <1> 	inc	ebx	; next in table
  2840                              <1> 	;dec	dx	; back to pointer register
  2841                              <1> 	; 02/02/2022
  2842                              <1> 	dec	dl ; 3D8h
  2843                              <1> 	loop	M10	; do the whole table
  2844                              <1> 	
  2845                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2846                              <1> 	;xor	ax, ax  
  2847                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2848                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2849                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2850                              <1> 	; black background, light gray characeter color, space character
  2851                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2852                              <1> ;M13:			  ; clear buffer
  2853                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2854                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2855                              <1> 
  2856                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2857                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2858                              <1> 			 ; prepare to output to video enable port
  2859                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2860                              <1> 	; 02/02/2022
  2861                              <1> 	;mov	dx, 3D8h
  2862                              <1> 	; 
  2863                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2864                              <1> 	mov	al, 29h
  2865                              <1> 	out	dx, al	 ; set video enable port
  2866                              <1> 
  2867                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2868                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2869                              <1> 	;
  2870                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2871                              <1> 	;
  2872                              <1> ;-----	SET CURSOR POSITIONS
  2873                              <1> 	;push	edi
  2874                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2875                              <1> 	mov	edi, cursor_posn
  2876                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2877                              <1> 	xor	eax, eax
  2878                              <1> 	rep 	stosd	; fill with zeroes
  2879                              <1> 	;pop	edi
  2880                              <1> 
  2881                              <1> ;-----	SET UP OVERSCAN REGISTER
  2882                              <1> 	inc	dx	; set overscan port to a default
  2883                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2884                              <1> ;M14:
  2885                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2886                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2887                              <1> 
  2888                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2889                              <1> 	;
  2890                              <1> 	pop	eax
  2891                              <1> 	pop	ecx ; 16/01/2016
  2892                              <1> 	pop	edx
  2893                              <1> 	pop	ebx
  2894                              <1> 	pop	edi ; 16/01/2016
  2895                              <1> 	retn
  2896                              <1> 
  2897                              <1> %endif
  2898                              <1> 	
  2899                              <1> tty_sw:
  2900                              <1> 	; 02/02/2022
  2901                              <1> 	; 30/06/2015
  2902                              <1> 	; 27/06/2015 
  2903                              <1> 	; 07/09/2014
  2904                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2905                              <1> 	;
  2906                              <1> 	; (Modified registers : EAX)
  2907                              <1> 	;
  2908                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2909                              <1> 	;
  2910                              <1> ;act_disp_page:
  2911                              <1> 	; 30/06/2015
  2912                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2913                              <1> 	; 10/12/2013
  2914                              <1> 	; 04/12/2013
  2915                              <1> 	;
  2916                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2917                              <1> 	;
  2918                              <1> 	; ACT_DISP_PAGE
  2919                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2920                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2921                              <1> 	; INPUT
  2922                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2923                              <1> 	; OUTPUT
  2924                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2925                              <1> 
  2926                              <1> 	;cli
  2927                              <1> 
  2928 000015E7 53                  <1> 	push	ebx
  2929                              <1> 	;push	cx
  2930                              <1> 	;push	dx
  2931                              <1> 	; 02/02/2022
  2932 000015E8 51                  <1> 	push	ecx
  2933 000015E9 52                  <1> 	push	edx
  2934                              <1> 	;
  2935 000015EA A2[C6700000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2936                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2937                              <1> 	;mov	cx, 25*80*2
  2938                              <1> 	; 02/02/2022
  2939 000015EF B9A00F0000          <1> 	mov	ecx, 25*80*2
  2940                              <1> 	; 27/06/2015
  2941 000015F4 0FB6D8              <1> 	movzx	ebx, al
  2942                              <1> 	; 02/02/2022
  2943 000015F7 89D8                <1> 	mov	eax, ebx
  2944                              <1> 	;
  2945                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2946                              <1> 	;mul 	cx	; display page times regen length
  2947                              <1> 	; 02/02/2022
  2948 000015F9 F7E1                <1> 	mul	ecx	
  2949                              <1> 	; 10/12/2013
  2950 000015FB 66A3[B4700000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2951                              <1> 	;mov	cx, ax	; start address to cx
  2952                              <1> 	; 02/02/2022
  2953 00001601 89C1                <1> 	mov	ecx, eax
  2954                              <1> 	;;sar	cx, 1
  2955                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2956                              <1> 	; 02/02/2022
  2957 00001603 D1E9                <1> 	shr	ecx, 1
  2958 00001605 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2959 00001607 E8F3FEFFFF          <1> 	call	m16
  2960                              <1> 	;sal	bx, 1
  2961                              <1> 	; 01/09/2014
  2962 0000160C D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2963 0000160E 81C3[B6700000]      <1> 	add	ebx, cursor_posn
  2964 00001614 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2965 00001617 E8CAFEFFFF          <1> 	call	m18
  2966                              <1> 	;
  2967                              <1> 	;pop	dx
  2968                              <1> 	;pop	cx
  2969                              <1> 	; 02/02/2022
  2970 0000161C 5A                  <1> 	pop	edx
  2971 0000161D 59                  <1> 	pop	ecx
  2972 0000161E 5B                  <1> 	pop	ebx
  2973                              <1> 	;
  2974                              <1> 	;sti
  2975                              <1> 	;
  2976 0000161F C3                  <1> 	retn
  2977                              <1> 
  2978                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2979                              <1> 
  2980                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1867                                  
  1868                                  setup_rtc_int:
  1869                                  ; source: http://wiki.osdev.org/RTC
  1870 00001620 FA                      	cli		; disable interrupts
  1871                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1872                                  	; in order to change this ...
  1873                                  	; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1874                                  	; (rate must be above 2 and not over 15)
  1875                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1876 00001621 B08A                    	mov	al, 8Ah 
  1877 00001623 E670                    	out	70h, al ; set index to register A, disable NMI
  1878 00001625 90                      	nop
  1879 00001626 E471                    	in	al, 71h ; get initial value of register A
  1880 00001628 88C4                    	mov 	ah, al
  1881 0000162A 80E4F0                  	and	ah, 0F0h
  1882 0000162D B08A                    	mov	al, 8Ah 
  1883 0000162F E670                    	out	70h, al ; reset index to register A
  1884 00001631 88E0                    	mov	al, ah
  1885 00001633 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1886 00001635 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1887                                  	; enable RTC interrupt
  1888 00001637 B08B                    	mov	al, 8Bh ;
  1889 00001639 E670                    	out	70h, al ; select register B and disable NMI
  1890 0000163B 90                      	nop
  1891 0000163C E471                    	in	al, 71h ; read the current value of register B
  1892 0000163E 88C4                    	mov	ah, al  ;
  1893 00001640 B08B                    	mov 	al, 8Bh ;
  1894 00001642 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1895 00001644 88E0                    	mov	al, ah  ;
  1896 00001646 0C40                    	or	al, 40h ;
  1897 00001648 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1898 0000164A FB                      	sti
  1899 0000164B C3                      	retn
  1900                                  
  1901                                  ; Write memory information
  1902                                  ; Temporary Code
  1903                                  ; 06/11/2014
  1904                                  ; 14/08/2015 
  1905                                  memory_info:	
  1906 0000164C A1[9C700000]            	mov	eax, [memory_size] ; in pages
  1907 00001651 50                      	push	eax
  1908 00001652 C1E00C                  	shl	eax, 12		   ; in bytes
  1909 00001655 BB0A000000              	mov	ebx, 10
  1910 0000165A 89D9                    	mov	ecx, ebx	   ; 10
  1911 0000165C BE[016D0000]            	mov	esi, mem_total_b_str	
  1912 00001661 E8AE000000              	call	bintdstr
  1913 00001666 58                      	pop	eax
  1914 00001667 B107                    	mov	cl, 7
  1915 00001669 BE[256D0000]            	mov	esi, mem_total_p_str
  1916 0000166E E8A1000000              	call	bintdstr	
  1917                                  	; 14/08/2015
  1918 00001673 E8B9000000              	call	calc_free_mem
  1919                                  	; edx = calculated free pages
  1920                                  	; ecx = 0
  1921 00001678 A1[A0700000]            	mov 	eax, [free_pages]
  1922 0000167D 39D0                    	cmp	eax, edx ; calculated free mem value 
  1923                                  		; and initial free mem value are same or not?
  1924 0000167F 751D                    	jne 	short pmim ; print mem info with '?' if not
  1925 00001681 52                      	push 	edx ; free memory in pages	
  1926                                  	;mov 	eax, edx
  1927 00001682 C1E00C                  	shl	eax, 12 ; convert page count
  1928                                  			; to byte count
  1929 00001685 B10A                    	mov	cl, 10
  1930 00001687 BE[456D0000]            	mov	esi, free_mem_b_str
  1931 0000168C E883000000              	call	bintdstr
  1932 00001691 58                      	pop	eax
  1933 00001692 B107                    	mov	cl, 7
  1934 00001694 BE[696D0000]            	mov	esi, free_mem_p_str
  1935 00001699 E876000000              	call	bintdstr
  1936                                  pmim:
  1937 0000169E BE[EF6C0000]            	mov	esi, msg_memory_info
  1938                                  pmim_nb:	
  1939 000016A3 AC                      	lodsb
  1940 000016A4 08C0                    	or	al, al
  1941 000016A6 740D                    	jz	short pmim_ok
  1942 000016A8 56                      	push	esi
  1943 000016A9 31DB                    	xor	ebx, ebx ; 0
  1944                                  			; Video page 0 (bl=0)
  1945 000016AB B407                    	mov	ah, 07h ; Black background, 
  1946                                  			; light gray forecolor
  1947 000016AD E812FDFFFF              	call	write_tty
  1948 000016B2 5E                      	pop	esi
  1949 000016B3 EBEE                    	jmp	short pmim_nb
  1950                                  pmim_ok:
  1951 000016B5 C3                      	retn
  1952                                  
  1953                                  ; Convert binary number to hexadecimal string
  1954                                  ; 10/05/2015  
  1955                                  ; dsectpm.s (28/02/2015)
  1956                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1957                                  ; 01/12/2014
  1958                                  ; 25/11/2014
  1959                                  ;
  1960                                  bytetohex:
  1961                                  	; INPUT ->
  1962                                  	; 	AL = byte (binary number)
  1963                                  	; OUTPUT ->
  1964                                  	;	AX = hexadecimal string
  1965                                  	;
  1966 000016B6 53                      	push	ebx
  1967 000016B7 31DB                    	xor	ebx, ebx
  1968 000016B9 88C3                    	mov	bl, al
  1969 000016BB C0EB04                  	shr	bl, 4
  1970 000016BE 8A9B[04170000]          	mov	bl, [ebx+hexchrs]
  1971 000016C4 86D8                    	xchg	bl, al
  1972 000016C6 80E30F                  	and	bl, 0Fh
  1973 000016C9 8AA3[04170000]          	mov	ah, [ebx+hexchrs]
  1974 000016CF 5B                      	pop	ebx	
  1975 000016D0 C3                      	retn
  1976                                  
  1977                                  wordtohex:
  1978                                  	; INPUT ->
  1979                                  	; 	AX = word (binary number)
  1980                                  	; OUTPUT ->
  1981                                  	;	EAX = hexadecimal string
  1982                                  	;
  1983 000016D1 53                      	push	ebx
  1984 000016D2 31DB                    	xor	ebx, ebx
  1985 000016D4 86E0                    	xchg	ah, al
  1986 000016D6 6650                    	push	ax
  1987 000016D8 88E3                    	mov	bl, ah
  1988 000016DA C0EB04                  	shr	bl, 4
  1989 000016DD 8A83[04170000]          	mov	al, [ebx+hexchrs]
  1990 000016E3 88E3                    	mov	bl, ah
  1991 000016E5 80E30F                  	and	bl, 0Fh
  1992 000016E8 8AA3[04170000]          	mov	ah, [ebx+hexchrs]
  1993 000016EE C1E010                  	shl	eax, 16
  1994 000016F1 6658                    	pop	ax
  1995 000016F3 5B                      	pop	ebx
  1996 000016F4 EBC0                    	jmp	short bytetohex
  1997                                  	;mov	bl, al
  1998                                  	;shr	bl, 4
  1999                                  	;mov	bl, [ebx+hexchrs]
  2000                                  	;xchg	bl, al	 	
  2001                                  	;and	bl, 0Fh
  2002                                  	;mov	ah, [ebx+hexchrs]
  2003                                  	;pop	ebx	
  2004                                  	;retn
  2005                                  
  2006                                  dwordtohex:
  2007                                  	; INPUT ->
  2008                                  	; 	EAX = dword (binary number)
  2009                                  	; OUTPUT ->
  2010                                  	;	EDX:EAX = hexadecimal string
  2011                                  	;
  2012 000016F6 50                      	push	eax
  2013 000016F7 C1E810                  	shr	eax, 16
  2014 000016FA E8D2FFFFFF              	call	wordtohex
  2015 000016FF 89C2                    	mov	edx, eax
  2016 00001701 58                      	pop	eax
  2017                                  	;call	wordtohex
  2018                                  	;retn
  2019                                  	; 02/01/2022
  2020 00001702 EBCD                    	jmp	short wordtohex
  2021                                  
  2022                                  ; 10/05/2015
  2023                                  hex_digits:
  2024                                  hexchrs:
  2025 00001704 303132333435363738-     	db '0123456789ABCDEF'
  2025 0000170D 39414243444546     
  2026                                  
  2027                                  ; Convert binary number to decimal/numeric string
  2028                                  ; 06/11/2014
  2029                                  ; Temporary Code
  2030                                  ;
  2031                                  
  2032                                  bintdstr:
  2033                                  	; EAX = binary number
  2034                                  	; ESI = decimal/numeric string address
  2035                                  	; EBX = divisor (10)
  2036                                  	; ECX = string length (<=10)
  2037 00001714 01CE                    	add	esi, ecx
  2038                                  btdstr0:
  2039 00001716 4E                      	dec	esi
  2040 00001717 31D2                    	xor	edx, edx
  2041 00001719 F7F3                    	div	ebx
  2042 0000171B 80C230                  	add	dl, 30h
  2043 0000171E 8816                    	mov	[esi], dl
  2044 00001720 FEC9                    	dec	cl
  2045 00001722 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2046 00001724 09C0                    	or	eax, eax
  2047 00001726 75EE                    	jnz	short btdstr0
  2048                                  btdstr1:
  2049 00001728 4E                      	dec	esi
  2050 00001729 C60620                          mov     byte [esi], 20h ; blank space
  2051 0000172C FEC9                    	dec	cl
  2052 0000172E 75F8                    	jnz	short btdstr1
  2053                                  btdstr2:
  2054 00001730 C3                      	retn
  2055                                  
  2056                                  ; Calculate free memory pages on M.A.T.
  2057                                  ; 06/11/2014
  2058                                  ; Temporary Code
  2059                                  ;
  2060                                  
  2061                                  calc_free_mem:
  2062 00001731 31D2                    	xor	edx, edx
  2063                                  	;xor	ecx, ecx
  2064                                  	;mov	cx, [mat_size] ; in pages
  2065                                  	; 02/01/2022
  2066 00001733 8B0D[B0700000]          	mov	ecx, [mat_size] ; in pages
  2067 00001739 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2068 0000173C BE00001000              	mov	esi, MEM_ALLOC_TBL
  2069                                  cfm0:
  2070 00001741 AD                      	lodsd
  2071 00001742 51                      	push	ecx
  2072 00001743 B920000000              	mov	ecx, 32
  2073                                  cfm1:
  2074 00001748 D1E8                    	shr	eax, 1
  2075 0000174A 7301                    	jnc	short cfm2
  2076 0000174C 42                      	inc	edx
  2077                                  cfm2:
  2078 0000174D E2F9                    	loop	cfm1
  2079 0000174F 59                      	pop	ecx
  2080 00001750 E2EF                    	loop	cfm0
  2081 00001752 C3                      	retn
  2082                                  
  2083                                  %include 'diskio.s'  ; 07/03/2015
  2084                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2085                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2086                              <1> ; ****************************************************************************
  2087                              <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC
  2088                              <1> ; Last Modification: 05/12/2021
  2089                              <1> ;
  2090                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2091                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2092                              <1> 
  2093                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2094                              <1> 
  2095                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2096                              <1> 
  2097                              <1> ; 06/02/2015
  2098                              <1> diskette_io:
  2099 00001753 9C                  <1> 	pushfd
  2100 00001754 0E                  <1> 	push 	cs
  2101 00001755 E809000000          <1> 	call 	DISKETTE_IO_1
  2102 0000175A C3                  <1> 	retn
  2103                              <1> 	
  2104                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2105                              <1> ;//////////////////////////////////////////////////////
  2106                              <1> 
  2107                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2108                              <1> ; 20/02/2015
  2109                              <1> ; 06/02/2015 (unix386.s)
  2110                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2111                              <1> ;
  2112                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2113                              <1> ;
  2114                              <1> ; ADISK.EQU
  2115                              <1> 
  2116                              <1> ;----- Wait control constants 
  2117                              <1> 
  2118                              <1> ;amount of time to wait while RESET is active.
  2119                              <1> 
  2120                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2121                              <1> 					;at 250 KBS xfer rate.
  2122                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2123                              <1> 
  2124                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2125                              <1> 					;status register to become valid
  2126                              <1> 					;before re-reading.
  2127                              <1> 
  2128                              <1> ;After sending a byte to NEC, status register may remain
  2129                              <1> ;incorrectly set for 24 us.
  2130                              <1> 
  2131                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2132                              <1> 					;RQM low.
  2133                              <1> 
  2134                              <1> ; COMMON.MAC
  2135                              <1> ;
  2136                              <1> ;	Timing macros
  2137                              <1> ;
  2138                              <1> 
  2139                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2140                              <1> 		jmp short $+2
  2141                              <1> %endmacro		
  2142                              <1> 
  2143                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2144                              <1> 		jmp short $+2
  2145                              <1> 		jmp short $+2
  2146                              <1> %endmacro
  2147                              <1> 
  2148                              <1> %macro		NEWIODELAY 0
  2149                              <1> 		out	0EBh,al
  2150                              <1> %endmacro 
  2151                              <1> 
  2152                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2153                              <1> ;;; WAIT_FOR_MEM
  2154                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2155                              <1> ;WAIT_FDU_INT_HI	equ	1
  2156                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2157                              <1> ;;; WAIT_FOR_PORT
  2158                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2159                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2160                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2161                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2162                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2163                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2164                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2165                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2166                              <1> ;;; WAIT_REFRESH
  2167                              <1> ;amount of time to wait for head settle, per unit in parameter
  2168                              <1> ;table = 1 ms.
  2169                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2170                              <1> 
  2171                              <1> 
  2172                              <1> ; //////////////// DISKETTE I/O ////////////////
  2173                              <1> 
  2174                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2175                              <1> 
  2176                              <1> ;----------------------------------------
  2177                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2178                              <1> ;----------------------------------------
  2179                              <1> 
  2180                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2181                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2182                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2183                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2184                              <1> 
  2185                              <1> ;----------------------------------------
  2186                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2187                              <1> ;-------------------------------------------------------------------------------
  2188                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2189                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2190                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2191                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2192                              <1> 
  2193                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2194                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2195                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2196                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2197                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2198                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2199                              <1> 
  2200                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2201                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2202                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2203                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2204                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2205                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2206                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2207                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2208                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2209                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2210                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2211                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2212                              <1> 
  2213                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2214                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2215                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2216                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2217                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2218                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2219                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2220                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2221                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2222                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2223                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2224                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2225                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2226                              <1> 
  2227                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2228                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2229                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2230                              <1> 
  2231                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2232                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2233                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2234                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2235                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2236                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2237                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2238                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2239                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2240                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2241                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2242                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2243                              <1> 
  2244                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2245                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2246                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2247                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2248                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2249                              <1> 
  2250                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2251                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2252                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2253                              <1> INTA01		EQU	021H		; 8259 PORT
  2254                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2255                              <1> INTB01		EQU	0A1H		;
  2256                              <1> 
  2257                              <1> ;-------------------------------------------------------------------------------
  2258                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2259                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2260                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2261                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2262                              <1> ;-------------------------------------------------------------------------------
  2263                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2264                              <1> 
  2265                              <1> ;-------------------------------------------------------------------------------
  2266                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2267                              <1> 
  2268                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2269                              <1> ; (unix386.s <-- dsectrm2.s)
  2270                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2271                              <1> 
  2272                              <1> ; 10/12/2014
  2273                              <1> ;
  2274                              <1> ;int40h:
  2275                              <1> ;	pushf
  2276                              <1> ;	push 	cs
  2277                              <1> ;	;cli
  2278                              <1> ;	call 	DISKETTE_IO_1
  2279                              <1> ;	retn
  2280                              <1> 
  2281                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2282                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2283                              <1> ;
  2284                              <1> 
  2285                              <1> ;-- INT13H ---------------------------------------------------------------------
  2286                              <1> ; DISKETTE I/O
  2287                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2288                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2289                              <1> ; INPUT
  2290                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2291                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2292                              <1> ;		ON ALL DRIVES
  2293                              <1> ;------------------------------------------------------------------------------- 
  2294                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2295                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2296                              <1> ;-------------------------------------------------------------------------------
  2297                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2298                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2299                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2300                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2301                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2302                              <1> ;		320/360	320/360	    0-39
  2303                              <1> ;		320/360	1.2M	    0-39
  2304                              <1> ;		1.2M	1.2M	    0-79
  2305                              <1> ;		720K	720K	    0-79
  2306                              <1> ;		1.44M	1.44M	    0-79	
  2307                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2308                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2309                              <1> ;		320/360	320/360	     1-8/9
  2310                              <1> ;		320/360	1.2M	     1-8/9
  2311                              <1> ;		1.2M	1.2M	     1-15
  2312                              <1> ;		720K	720K	     1-9
  2313                              <1> ;		1.44M	1.44M	     1-18		
  2314                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2315                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2316                              <1> ;		320/360	320/360	        8/9
  2317                              <1> ;		320/360	1.2M	        8/9
  2318                              <1> ;		1.2M	1.2M		15
  2319                              <1> ;		720K	720K		9
  2320                              <1> ;		1.44M	1.44M		18
  2321                              <1> ;
  2322                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2323                              <1> ;
  2324                              <1> ;-------------------------------------------------------------------------------
  2325                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2326                              <1> ;-------------------------------------------------------------------------------
  2327                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2328                              <1> ;-------------------------------------------------------------------------------
  2329                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2330                              <1> ;-------------------------------------------------------------------------------
  2331                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2332                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2333                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2334                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2335                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2336                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2337                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2338                              <1> ;		READ/WRITE ACCESS.
  2339                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2340                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2341                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2342                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2343                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2344                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2345                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2346                              <1> ;
  2347                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2348                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2349                              <1> ;		---------------------------------------------
  2350                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2351                              <1> ;		---------------------------------------------
  2352                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2353                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2354                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2355                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2356                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2357                              <1> ;		---------------------------------------------
  2358                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2359                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2360                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2361                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2362                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2363                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2364                              <1> ;-------------------------------------------------------------------------------
  2365                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2366                              <1> ;	REGISTERS
  2367                              <1> ;	  INPUT
  2368                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2369                              <1> ;	  OUTPUT
  2370                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2371                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2372                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2373                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2374                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2375                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2376                              <1> ;	    (BH) - 0
  2377                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2378                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2379                              <1> ;	    (AX) - 0
  2380                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2381                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2382                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2383                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2384                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2385                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2386                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2387                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2388                              <1> ;-------------------------------------------------------------------------------
  2389                              <1> ;	(AH)= 15H  READ DASD TYPE
  2390                              <1> ;	OUTPUT REGISTERS
  2391                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2392                              <1> ;		00 - DRIVE NOT PRESENT	
  2393                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2394                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2395                              <1> ;		03 - RESERVED (FIXED DISK)
  2396                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2397                              <1> ;-------------------------------------------------------------------------------
  2398                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2399                              <1> ;	OUTPUT REGISTERS
  2400                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2401                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2402                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2403                              <1> ;-------------------------------------------------------------------------------
  2404                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2405                              <1> ;	INPUT REGISTERS
  2406                              <1> ;	(AL) -	00 - NOT USED	
  2407                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2408                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2409                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2410                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2411                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2412                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2413                              <1> ;-------------------------------------------------------------------------------
  2414                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2415                              <1> ;	INPUT REGISTERS
  2416                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2417                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2418                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2419                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2420                              <1> ;	OUTPUT REGISTERS:
  2421                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2422                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2423                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2424                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2425                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2426                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2427                              <1> ;-------------------------------------------------------------------------------
  2428                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2429                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2430                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2431                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2432                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2433                              <1> ;		CHANGE ERROR CODE
  2434                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2435                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2436                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2437                              <1> ;
  2438                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2439                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2440                              <1> ;-------------------------------------------------------------------------------
  2441                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2442                              <1> ;	AH = STATUS OF OPERATION
  2443                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2444                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2445                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2446                              <1> ;		TYPE AH=(15)).
  2447                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2448                              <1> ;	FOR READ/WRITE/VERIFY
  2449                              <1> ;		DS,BX,DX,CX PRESERVED
  2450                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2451                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2452                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2453                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2454                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2455                              <1> ;-------------------------------------------------------------------------------
  2456                              <1> ;
  2457                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2458                              <1> ;
  2459                              <1> ;   -----------------------------------------------------------------
  2460                              <1> ;   |       |       |       |       |       |       |       |       |
  2461                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2462                              <1> ;   |       |       |       |       |       |       |       |       |
  2463                              <1> ;   -----------------------------------------------------------------
  2464                              <1> ;	|	|	|	|	|	|	|	|
  2465                              <1> ;	|	|	|	|	|	-----------------
  2466                              <1> ;	|	|	|	|	|		|
  2467                              <1> ;	|	|	|	|    RESERVED		|
  2468                              <1> ;	|	|	|	|		  PRESENT STATE
  2469                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2470                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2471                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2472                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2473                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2474                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2475                              <1> ;	|	|	|	|	110: RESERVED
  2476                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2477                              <1> ;	|	|	|	|
  2478                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2479                              <1> ;	|	|	|
  2480                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2481                              <1> ;	|	|			DRIVE)
  2482                              <1> ;	|	|
  2483                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2484                              <1> ;
  2485                              <1> ;						00: 500 KBS
  2486                              <1> ;						01: 300 KBS
  2487                              <1> ;						10: 250 KBS
  2488                              <1> ;						11: RESERVED
  2489                              <1> ;
  2490                              <1> ;
  2491                              <1> ;-------------------------------------------------------------------------------
  2492                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2493                              <1> ;-------------------------------------------------------------------------------
  2494                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2495                              <1> ;-------------------------------------------------------------------------------
  2496                              <1> 
  2497                              <1> struc MD
  2498 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2499 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2500 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2501 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2502 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2503 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2504 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2505 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2506 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2507 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2508 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2509 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2510 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2511                              <1> endstruc
  2512                              <1> 
  2513                              <1> BIT7OFF	EQU	7FH
  2514                              <1> BIT7ON	EQU	80H
  2515                              <1> 
  2516                              <1> ;;int13h: ; 16/02/2015
  2517                              <1> ;; 16/02/2015 - 21/02/2015
  2518                              <1> int40h:
  2519 0000175B 9C                  <1> 	pushfd
  2520 0000175C 0E                  <1> 	push 	cs
  2521 0000175D E801000000          <1> 	call 	DISKETTE_IO_1
  2522 00001762 C3                  <1> 	retn	
  2523                              <1> 
  2524                              <1> DISKETTE_IO_1:
  2525                              <1> 
  2526 00001763 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2527 00001764 55                  <1> 	PUSH	eBP			; USER REGISTER
  2528 00001765 57                  <1> 	PUSH	eDI			; USER REGISTER
  2529 00001766 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2530 00001767 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2531 00001768 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2532 00001769 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2533                              <1> 					; [BP]   = SECTOR #
  2534                              <1> 					; [BP+1] = TRACK #
  2535                              <1> 					; [BP+2] = BUFFER OFFSET
  2536                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2537                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2538                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2539                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2540                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2541                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2542                              <1> 					; BH/[BP+3] = 0
  2543                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2544                              <1> 					; DH/[BP+5] = MAX HEAD #
  2545                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2546 0000176B 06                  <1> 	push	es ; 06/02/2015	
  2547 0000176C 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2548 0000176D 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2549                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2550                              <1> 	;mov	cx, cs
  2551                              <1> 	;mov	ds, cx
  2552 0000176E 66B91000            <1> 	mov	cx, KDATA
  2553 00001772 8ED9                <1>         mov     ds, cx
  2554 00001774 8EC1                <1>         mov     es, cx
  2555                              <1> 
  2556                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2557 00001776 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2558 00001779 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2559 0000177B B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2560                              <1> OK_FUNC:
  2561 0000177D 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2562 00001780 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2563 00001782 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2564 00001785 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2565 00001787 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2566 0000178A 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2567 0000178C B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2568                              <1> OK_DRV:
  2569 0000178E 31C9                <1> 	xor	ecx, ecx
  2570                              <1> 	;mov	esi, ecx ; 08/02/2015
  2571                              <1> 	; 05/12/2021
  2572 00001790 89CE                <1> 	mov	esi, ecx
  2573 00001792 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2574 00001794 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2575                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2576                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2577 00001796 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2578 00001799 BB[D1170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2579 0000179E 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2580 000017A0 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2581 000017A2 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2582 000017A4 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2583 000017A7 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2584                              <1> 	;
  2585                              <1> 	; 11/12/2014
  2586 000017AA 8815[816B0000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2587                              <1> 	;
  2588 000017B0 8A25[1C710000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2589 000017B6 C605[1C710000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2590                              <1> 
  2591                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2592                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2593                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2594                              <1> ;
  2595                              <1> ;		DI	: DRIVE #
  2596                              <1> ;		SI-HI	: HEAD #
  2597                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2598                              <1> ;		ES	: BUFFER SEGMENT
  2599                              <1> ;		[BP]	: SECTOR #
  2600                              <1> ;		[BP+1]	: TRACK #
  2601                              <1> ;		[BP+2]	: BUFFER OFFSET
  2602                              <1> ;
  2603                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2604                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2605                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2606                              <1> ;	SPECIFIC ERROR CODE.
  2607                              <1> ;
  2608                              <1> 					; (AH) = @DSKETTE_STATUS
  2609 000017BD FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2610 000017BF 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2611 000017C0 1F                  <1> 	POP	DS
  2612 000017C1 07                  <1> 	pop	es	; 06/02/2015
  2613 000017C2 59                  <1> 	POP	eCX
  2614 000017C3 5B                  <1> 	POP	eBX
  2615 000017C4 5A                  <1> 	POP	eDX
  2616 000017C5 5F                  <1> 	POP	eDI
  2617 000017C6 89E5                <1> 	MOV	eBP, eSP
  2618 000017C8 50                  <1> 	PUSH	eAX
  2619 000017C9 9C                  <1> 	PUSHFd
  2620 000017CA 58                  <1> 	POP	eAX
  2621                              <1> 	;MOV	[BP+6], AX
  2622 000017CB 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2623 000017CE 58                  <1> 	POP	eAX
  2624 000017CF 5D                  <1> 	POP	eBP
  2625 000017D0 CF                  <1> 	IRETd
  2626                              <1> 
  2627                              <1> ;-------------------------------------------------------------------------------
  2628                              <1> ; DW --> dd (06/02/2015)
  2629 000017D1 [35180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2630 000017D5 [AA180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2631 000017D9 [BA180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2632 000017DD [CB180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2633 000017E1 [DC180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2634 000017E5 [ED180000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2635 000017E9 [71190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2636 000017ED [71190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2637 000017F1 [7D190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2638 000017F5 [71190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2639 000017F9 [71190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2640 000017FD [71190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2641 00001801 [71190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2642 00001805 [71190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2643 00001809 [71190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2644 0000180D [71190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2645 00001811 [71190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2646 00001815 [71190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2647 00001819 [71190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2648 0000181D [71190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2649 00001821 [71190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2650 00001825 [3C1A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2651 00001829 [641A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2652 0000182D [9D1A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2653 00001831 [1E1B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2654                              <1> FNC_TAE EQU     $                       ; END
  2655                              <1> 
  2656                              <1> ;-------------------------------------------------------------------------------
  2657                              <1> ; DISK_RESET	(AH = 00H)	
  2658                              <1> ;		RESET THE DISKETTE SYSTEM.
  2659                              <1> ;
  2660                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2661                              <1> ;-------------------------------------------------------------------------------
  2662                              <1> DSK_RESET:
  2663 00001835 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2664 00001839 FA                  <1> 	CLI				; NO INTERRUPTS
  2665 0000183A A0[1A710000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2666 0000183F 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2667 00001841 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2668                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2669 00001844 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2670 00001846 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2671 00001847 C605[19710000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2672                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2673                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2674                              <1> 					;      PULSE WIDTH)
  2675                              <1> 	; 19/12/2014
  2676                              <1> 	NEWIODELAY
  2149 0000184E E6EB                <2>  out 0EBh,al
  2677                              <1> 
  2678                              <1> 	; 17/12/2014 
  2679                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2680 00001850 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2681                              <1> wdw1:
  2682                              <1> 	NEWIODELAY   ; 27/02/2015
  2149 00001855 E6EB                <2>  out 0EBh,al
  2683 00001857 E2FC                <1> 	loop	wdw1
  2684                              <1> 	;
  2685 00001859 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2686 0000185B EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2687                              <1> 	; 16/12/2014
  2688                              <1> 	IODELAY
  2144 0000185C EB00                <2>  jmp short $+2
  2145 0000185E EB00                <2>  jmp short $+2
  2689                              <1> 	;
  2690                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2691 00001860 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2692 00001865 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2693 00001867 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2694                              <1> NXT_DRV:
  2695                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2696                              <1> 	; 05/12/2021
  2697 0000186B 51                  <1> 	push	ecx
  2698 0000186C B8[A0180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2699 00001871 50                  <1> 	PUSH	eAX			; "
  2700 00001872 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2701 00001874 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2702 00001879 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2703 0000187A E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2704                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2705                              <1> 	; 05/12/2021
  2706 0000187F 59                  <1> 	pop	ecx
  2707 00001880 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2708 00001882 3A0D[1D710000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2709 00001888 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2710 0000188A FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2711 0000188C 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2712 0000188F 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2713                              <1> 	;
  2714 00001891 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2715                              <1> RESBAC:
  2716 00001896 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2717                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2718                              <1> 	; 05/12/2021
  2719 0000189B 89F3                <1> 	mov	ebx, esi
  2720 0000189D 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2721 0000189F C3                  <1> 	RETn		
  2722                              <1> DR_POP_ERR:
  2723                              <1> 	;POP	CX			; CLEAR STACK
  2724                              <1> 	; 05/12/2021
  2725 000018A0 59                  <1> 	pop	ecx
  2726                              <1> DR_ERR:
  2727 000018A1 800D[1C710000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2728 000018A8 EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2729                              <1> 
  2730                              <1> ;-------------------------------------------------------------------------------
  2731                              <1> ; DISK_STATUS	(AH = 01H)
  2732                              <1> ;	DISKETTE STATUS.
  2733                              <1> ;
  2734                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2735                              <1> ;
  2736                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2737                              <1> ;-------------------------------------------------------------------------------
  2738                              <1> DSK_STATUS:
  2739 000018AA 8825[1C710000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2740 000018B0 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2741                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2742                              <1> 	; 05/12/2021
  2743 000018B5 89F3                <1> 	mov	ebx, esi
  2744 000018B7 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2745 000018B9 C3                  <1> 	RETn		
  2746                              <1> 
  2747                              <1> ;-------------------------------------------------------------------------------
  2748                              <1> ; DISK_READ	(AH = 02H)	
  2749                              <1> ;	DISKETTE READ.
  2750                              <1> ;
  2751                              <1> ; ON ENTRY:	DI	: DRIVE #
  2752                              <1> ;		SI-HI	: HEAD #
  2753                              <1> ;		SI-LOW	: # OF SECTORS
  2754                              <1> ;		ES	: BUFFER SEGMENT
  2755                              <1> ;		[BP]	: SECTOR #
  2756                              <1> ;		[BP+1]	: TRACK #
  2757                              <1> ;		[BP+2]	: BUFFER OFFSET
  2758                              <1> ;
  2759                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2760                              <1> ;-------------------------------------------------------------------------------
  2761                              <1> 
  2762                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2763                              <1> 
  2764                              <1> DSK_READ:
  2765 000018BA 8025[1A710000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2766 000018C1 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2767 000018C5 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2768 000018CA C3                  <1> 	RETn
  2769                              <1> 
  2770                              <1> ;-------------------------------------------------------------------------------
  2771                              <1> ; DISK_WRITE	(AH = 03H)
  2772                              <1> ;	DISKETTE WRITE.
  2773                              <1> ;
  2774                              <1> ; ON ENTRY:	DI	: DRIVE #
  2775                              <1> ;		SI-HI	: HEAD #
  2776                              <1> ;		SI-LOW	: # OF SECTORS
  2777                              <1> ;		ES	: BUFFER SEGMENT
  2778                              <1> ;		[BP]	: SECTOR #
  2779                              <1> ;		[BP+1]	: TRACK #
  2780                              <1> ;		[BP+2]	: BUFFER OFFSET
  2781                              <1> ;
  2782                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2783                              <1> ;-------------------------------------------------------------------------------
  2784                              <1> 
  2785                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2786                              <1> 
  2787                              <1> DSK_WRITE:
  2788 000018CB 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2789 000018CF 800D[1A710000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2790 000018D6 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2791 000018DB C3                  <1> 	RETn
  2792                              <1> 
  2793                              <1> ;-------------------------------------------------------------------------------
  2794                              <1> ; DISK_VERF	(AH = 04H)
  2795                              <1> ;	DISKETTE VERIFY.
  2796                              <1> ;
  2797                              <1> ; ON ENTRY:	DI	: DRIVE #
  2798                              <1> ;		SI-HI	: HEAD #
  2799                              <1> ;		SI-LOW	: # OF SECTORS
  2800                              <1> ;		ES	: BUFFER SEGMENT
  2801                              <1> ;		[BP]	: SECTOR #
  2802                              <1> ;		[BP+1]	: TRACK #
  2803                              <1> ;		[BP+2]	: BUFFER OFFSET
  2804                              <1> ;
  2805                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2806                              <1> ;-------------------------------------------------------------------------------
  2807                              <1> DSK_VERF:
  2808 000018DC 8025[1A710000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2809 000018E3 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2810 000018E7 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2811 000018EC C3                  <1> 	RETn
  2812                              <1> 
  2813                              <1> ;-------------------------------------------------------------------------------
  2814                              <1> ; DISK_FORMAT	(AH = 05H)
  2815                              <1> ;	DISKETTE FORMAT.
  2816                              <1> ;
  2817                              <1> ; ON ENTRY:	DI	: DRIVE #
  2818                              <1> ;		SI-HI	: HEAD #
  2819                              <1> ;		SI-LOW	: # OF SECTORS
  2820                              <1> ;		ES	: BUFFER SEGMENT
  2821                              <1> ;		[BP]	: SECTOR #
  2822                              <1> ;		[BP+1]	: TRACK #
  2823                              <1> ;		[BP+2]	: BUFFER OFFSET
  2824                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2825                              <1> ;
  2826                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2827                              <1> ;-------------------------------------------------------------------------------
  2828                              <1> DSK_FORMAT:
  2829 000018ED E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2830 000018F2 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2831 000018F7 800D[1A710000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2832 000018FE E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2833 00001903 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2834 00001905 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2835 0000190A E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2836 0000190F 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2837 00001911 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2838                              <1> FM_WR:
  2839 00001916 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2840 0000191B 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2841 0000191D B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2842 0000191F E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2843 00001924 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2844 00001926 B8[62190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2845 0000192B 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2846 0000192C B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2847 0000192E E80E090000          <1> 	CALL	GET_PARM
  2848 00001933 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2849 00001938 B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2850 0000193A E802090000          <1> 	CALL	GET_PARM
  2851 0000193F E8030A0000          <1> 	CALL	NEC_OUTPUT
  2852 00001944 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2853 00001946 E8F6080000          <1> 	CALL	GET_PARM
  2854 0000194B E8F7090000          <1> 	CALL	NEC_OUTPUT
  2855 00001950 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2856 00001952 E8EA080000          <1> 	CALL	GET_PARM
  2857 00001957 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2858 0000195C 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2859 0000195D E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2860                              <1> FM_DON:
  2861 00001962 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2862 00001967 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2863                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2864 0000196C 89F3                <1> 	mov	ebx, esi ; 05/12/2021
  2865 0000196E 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2866 00001970 C3                  <1> 	RETn
  2867                              <1> 
  2868                              <1> ;-------------------------------------------------------------------------------
  2869                              <1> ; FNC_ERR
  2870                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2871                              <1> ;	SET BAD COMMAND IN STATUS.
  2872                              <1> ;
  2873                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2874                              <1> ;-------------------------------------------------------------------------------
  2875                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2876                              <1> 	;MOV	AX,SI			; RESTORE AL
  2877                              <1> 	; 05/12/2021
  2878 00001971 89F0                <1> 	mov	eax, esi
  2879 00001973 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2880 00001975 8825[1C710000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2881 0000197B F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2882 0000197C C3                  <1> 	RETn
  2883                              <1> 
  2884                              <1> ;-------------------------------------------------------------------------------
  2885                              <1> ; DISK_PARMS	(AH = 08H)	
  2886                              <1> ;	READ DRIVE PARAMETERS.
  2887                              <1> ;
  2888                              <1> ; ON ENTRY:	DI : DRIVE #
  2889                              <1> ;
  2890                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2891                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2892                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2893                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2894                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2895                              <1> ;		BH/[BP+3] = 0
  2896                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2897                              <1> ;		DH/[BP+5] = MAX HEAD #
  2898                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2899                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2900                              <1> ;		AX        = 0
  2901                              <1> ;
  2902                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2903                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2904                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2905                              <1> ;		       CALLER.
  2906                              <1> ;-------------------------------------------------------------------------------
  2907                              <1> DSK_PARMS:
  2908 0000197D E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2909                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2910 00001982 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2911 00001984 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2912                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2913                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2914                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2915                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2916                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2917                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2918                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2919                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2920                              <1> 	;sub	edx, edx
  2921 00001987 66A1[8E6B0000]      <1> 	mov     ax, [fd0_type]
  2922 0000198D 6621C0              <1> 	and     ax, ax
  2923 00001990 7473                <1> 	jz      short NON_DRV
  2924 00001992 FEC2                <1> 	inc     dl
  2925 00001994 20E4                <1> 	and     ah, ah
  2926 00001996 7402                <1> 	jz      short STO_DL
  2927 00001998 FEC2                <1> 	inc     dl
  2928                              <1> STO_DL:
  2929                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2930 0000199A 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2931 0000199D 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2932 000019A1 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2933                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2934 000019A3 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2935 000019A7 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2936                              <1> 	;;20/02/2015
  2937                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2938                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2939 000019AC 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2940 000019AE E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2941 000019B3 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2942                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2943 000019B5 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2944 000019B8 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2945 000019BB 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2946 000019BE EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2947                              <1> CHK_EST:
  2948 000019C0 8AA7[29710000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2949 000019C6 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2950 000019C9 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2951                              <1> USE_EST:
  2952 000019CB 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2953 000019CE 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2954 000019D1 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2955                              <1> 
  2956                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2957                              <1> 
  2958 000019D3 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2959 000019D5 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2960 000019DA 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2961 000019DD 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2962 000019E0 F687[29710000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2963 000019E7 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2964                              <1> 
  2965                              <1> ;-----	IT IS 1.44 MB DRIVE
  2966                              <1> 
  2967                              <1> PARM144:
  2968 000019E9 B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2969 000019EB E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2970 000019F0 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2971 000019F3 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2972                              <1> STO_CX:
  2973 000019F6 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2974                              <1> ES_DI:
  2975                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2976 000019F9 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2977                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2978                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2979                              <1> DP_OUT:
  2980 000019FC E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2981                              <1> 	;XOR	AX,AX			; CLEAR
  2982                              <1> 	; 05/12/2021
  2983 00001A01 31C0                <1> 	xor	eax, eax
  2984 00001A03 F8                  <1> 	CLC
  2985 00001A04 C3                  <1> 	RETn
  2986                              <1> 
  2987                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2988                              <1> 
  2989                              <1> NON_DRV:
  2990                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2991 00001A05 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2992                              <1> NON_DRV1:
  2993 00001A08 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2994 00001A0D 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2995                              <1> 
  2996                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2997                              <1> 	
  2998 00001A0F E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2999                              <1> 	;MOV	AX,SI			; RESTORE AL
  3000 00001A14 89F0                <1> 	mov	eax, esi ; 05/12/2021
  3001 00001A16 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  3002 00001A18 F9                  <1> 	STC
  3003 00001A19 C3                  <1> 	RETn
  3004                              <1> 
  3005                              <1> NON_DRV2:
  3006                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  3007 00001A1A 31C0                <1> 	xor	eax, eax	
  3008 00001A1C 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  3009                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  3010 00001A20 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  3011                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  3012 00001A23 89450C              <1> 	mov	[ebp+12], eax
  3013                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  3014 00001A26 EBD4                <1> 	JMP	SHORT DP_OUT
  3015                              <1> 
  3016                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  3017                              <1> 
  3018                              <1> USE_EST2:
  3019 00001A28 B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  3020 00001A2A E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3021 00001A2F 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3022 00001A32 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  3023 00001A35 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3024 00001A38 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  3025 00001A3A EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  3026                              <1> 
  3027                              <1> ;-------------------------------------------------------------------------------
  3028                              <1> ; DISK_TYPE (AH = 15H)	
  3029                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  3030                              <1> ;
  3031                              <1> ;  ON ENTRY:	DI = DRIVE #
  3032                              <1> ;
  3033                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  3034                              <1> ;-------------------------------------------------------------------------------
  3035                              <1> DSK_TYPE:
  3036 00001A3C E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3037 00001A41 8A87[29710000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  3038 00001A47 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  3039 00001A49 7415                <1> 	JZ	short NO_DRV
  3040 00001A4B B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3041 00001A4D A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3042 00001A4F 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3043 00001A51 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3044                              <1> DT_BACK:
  3045                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3046 00001A53 50                  <1> 	push	eax ; 05/12/2021
  3047 00001A54 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3048                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3049 00001A59 58                  <1> 	pop	eax ; 05/12/2021
  3050 00001A5A F8                  <1> 	CLC				; NO ERROR
  3051                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3052                              <1> 	; 05/12/2021
  3053 00001A5B 89F3                <1> 	mov	ebx, esi
  3054 00001A5D 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3055 00001A5F C3                  <1> 	RETn
  3056                              <1> NO_DRV:	
  3057 00001A60 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3058 00001A62 EBEF                <1> 	JMP	SHORT DT_BACK
  3059                              <1> 
  3060                              <1> ;-------------------------------------------------------------------------------
  3061                              <1> ; DISK_CHANGE	(AH = 16H)
  3062                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3063                              <1> ;
  3064                              <1> ; ON ENTRY:	DI = DRIVE #
  3065                              <1> ;
  3066                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3067                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3068                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3069                              <1> ;-------------------------------------------------------------------------------
  3070                              <1> DSK_CHANGE:
  3071 00001A64 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3072 00001A69 8A87[29710000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3073 00001A6F 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3074 00001A71 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3075 00001A73 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3076 00001A75 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3077                              <1> DC0:
  3078 00001A77 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3079 00001A7C 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3080                              <1> 
  3081 00001A7E C605[1C710000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3082                              <1> 
  3083 00001A85 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3084 00001A8A E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3085                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3086                              <1> 	; 05/12/2021
  3087 00001A8F 89F3                <1> 	mov	ebx, esi
  3088 00001A91 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3089 00001A93 C3                  <1> 	RETn
  3090                              <1> DC_NON:
  3091 00001A94 800D[1C710000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3092 00001A9B EBE8                <1> 	JMP	SHORT FINIS
  3093                              <1> 
  3094                              <1> ;-------------------------------------------------------------------------------
  3095                              <1> ; FORMAT_SET	(AH = 17H)
  3096                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3097                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3098                              <1> ;
  3099                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3100                              <1> ;		DI     = DRIVE #
  3101                              <1> ;
  3102                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3103                              <1> ;		AH = @DSKETTE_STATUS
  3104                              <1> ;		CY = 1 IF ERROR
  3105                              <1> ;-------------------------------------------------------------------------------
  3106                              <1> FORMAT_SET:
  3107 00001A9D E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3108                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3109                              <1> 	; 05/12/2021
  3110 00001AA2 56                  <1> 	push	esi
  3111 00001AA3 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3112 00001AA6 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3113 00001AA8 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3114 00001AAB 80A7[29710000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3115 00001AB2 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3116 00001AB4 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3117 00001AB6 808F[29710000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3118 00001ABD EB48                <1> 	JMP	SHORT S0
  3119                              <1> NOT_320:
  3120 00001ABF E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3121 00001AC4 803D[1C710000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3122 00001ACB 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3123                              <1> S3:
  3124 00001ACD 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3125 00001ACF 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3126 00001AD1 808F[29710000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3127 00001AD8 EB2D                <1> 	JMP	SHORT S0
  3128                              <1> NOT_320_12:
  3129 00001ADA 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3130 00001ADC 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3131 00001ADE 808F[29710000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3132 00001AE5 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3133                              <1> NOT_12:	
  3134 00001AE7 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3135 00001AE9 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3136                              <1> 
  3137 00001AEB F687[29710000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3138 00001AF2 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3139 00001AF4 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3140 00001AF6 F687[29710000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3141 00001AFD 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3142                              <1> ASSUME:
  3143 00001AFF B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3144                              <1> OR_IT_IN:
  3145 00001B01 0887[29710000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3146                              <1> S0:
  3147 00001B07 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3148 00001B0C E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3149                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3150                              <1> 	; 05/12/2021
  3151 00001B11 5B                  <1> 	pop	ebx
  3152 00001B12 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3153 00001B14 C3                  <1> 	RETn
  3154                              <1> FS_ERR:
  3155 00001B15 C605[1C710000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3156 00001B1C EBE9                <1> 	JMP	SHORT S0
  3157                              <1> 
  3158                              <1> ;-------------------------------------------------------------------------------
  3159                              <1> ; SET_MEDIA	(AH = 18H)
  3160                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3161                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3162                              <1> ;
  3163                              <1> ; ON ENTRY:
  3164                              <1> ;	[BP]	= SECTOR PER TRACK
  3165                              <1> ;	[BP+1]	= TRACK #
  3166                              <1> ;	DI	= DRIVE #
  3167                              <1> ;
  3168                              <1> ; ON EXIT:
  3169                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3170                              <1> ;	IF NO ERROR:
  3171                              <1> ;		AH = 0
  3172                              <1> ;		CY = 0
  3173                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3174                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3175                              <1> ;	IF ERROR:	
  3176                              <1> ;		AH = @DSKETTE_STATUS
  3177                              <1> ;		CY = 1
  3178                              <1> ;-------------------------------------------------------------------------------
  3179                              <1> SET_MEDIA:
  3180 00001B1E E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3181 00001B23 F687[29710000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3182 00001B2A 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3183 00001B2C E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3184 00001B31 803D[1C710000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3185 00001B38 746B                <1> 	JE	short SM_RTN
  3186 00001B3A C605[1C710000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3187                              <1> SM_CMOS:
  3188 00001B41 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3189                              <1> 	;;20/02/2015
  3190                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3191                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3192 00001B46 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3193 00001B48 E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3194 00001B4D 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3195 00001B4F 57                  <1> 	PUSH	eDI			; SAVE REG.
  3196 00001B50 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3197 00001B52 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3198                              <1> DR_SEARCH:
  3199 00001B57 8AA3[0C6B0000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3200 00001B5D 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3201 00001B60 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3202 00001B62 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3203                              <1> DR_FND:
  3204 00001B64 8BBB[0D6B0000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3205                              <1> MD_SEARCH:
  3206 00001B6A 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3207 00001B6D 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3208 00001B70 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3209 00001B72 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3210 00001B75 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3211 00001B78 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3212                              <1> NXT_MD:
  3213                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3214 00001B7A 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3215 00001B7D E2D8                <1> 	LOOP    DR_SEARCH
  3216 00001B7F 5F                  <1> 	POP	eDI			; RESTORE REG.
  3217                              <1> MD_NOT_FND:
  3218 00001B80 C605[1C710000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3219 00001B87 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3220                              <1> MD_FND:
  3221 00001B89 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3222 00001B8C 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3223 00001B8E 7502                <1> 	JNE	short MD_SET
  3224 00001B90 0C20                <1> 	OR	AL,DBL_STEP
  3225                              <1> MD_SET:
  3226                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3227 00001B92 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3228 00001B95 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3229 00001B97 5F                  <1> 	POP	eDI
  3230 00001B98 80A7[29710000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3231 00001B9F 0887[29710000]      <1> 	OR	[DSK_STATE+eDI], AL
  3232                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3233                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3234                              <1> SM_RTN:
  3235 00001BA5 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3236 00001BAA E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3237 00001BAF C3                  <1> 	RETn
  3238                              <1> 
  3239                              <1> ;----------------------------------------------------------------
  3240                              <1> ; DR_TYPE_CHECK							:
  3241                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3242                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3243                              <1> ; ON ENTRY:							:
  3244                              <1> ;	AL = DRIVE TYPE						:
  3245                              <1> ; ON EXIT:							:
  3246                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3247                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3248                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3249                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3250                              <1> ; REGISTERS ALTERED: eBX						:
  3251                              <1> ;----------------------------------------------------------------		
  3252                              <1> DR_TYPE_CHECK:
  3253                              <1> 	;PUSH	AX			
  3254                              <1> 	; 05/12/2021
  3255 00001BB0 50                  <1> 	push	eax
  3256 00001BB1 51                  <1> 	PUSH	eCX
  3257 00001BB2 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3258 00001BB4 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3259                              <1> TYPE_CHK:	
  3260 00001BB9 8AA3[0C6B0000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3261 00001BBF 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3262 00001BC1 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3263                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3264 00001BC3 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3265 00001BC6 E2F1                <1> 	LOOP    TYPE_CHK
  3266                              <1> 	;
  3267 00001BC8 BB[6B6B0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3268                              <1> 					; Default for GET_PARM (11/12/2014)
  3269                              <1> 	;
  3270 00001BCD F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3271 00001BCE EB06                <1> 	JMP	SHORT TYPE_RTN
  3272                              <1> DR_TYPE_VALID:
  3273 00001BD0 8B9B[0D6B0000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3274                              <1> TYPE_RTN:
  3275 00001BD6 59                  <1> 	POP	eCX
  3276                              <1> 	;POP	AX
  3277                              <1> 	; 05/12/2021
  3278 00001BD7 58                  <1> 	pop	eax
  3279 00001BD8 C3                  <1> 	RETn	
  3280                              <1> 		
  3281                              <1> ;----------------------------------------------------------------
  3282                              <1> ; SEND_SPEC							:
  3283                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3284                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3285                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3286                              <1> ; ON EXIT:	NONE						:	
  3287                              <1> ; REGISTERS ALTERED: CX, DX					:
  3288                              <1> ;----------------------------------------------------------------		
  3289                              <1> SEND_SPEC:
  3290 00001BD9 50                  <1> 	PUSH	eAX			; SAVE AX
  3291 00001BDA B8[001C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3292 00001BDF 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3293 00001BE0 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3294 00001BE2 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3295 00001BE7 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3296 00001BE9 E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3297 00001BEE E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3298 00001BF3 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3299 00001BF5 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3300 00001BFA E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3301 00001BFF 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3302                              <1> SPECBAC:
  3303 00001C00 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3304 00001C01 C3                  <1> 	RETn
  3305                              <1> 
  3306                              <1> ;----------------------------------------------------------------
  3307                              <1> ; SEND_SPEC_MD							:
  3308                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3309                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3310                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3311                              <1> ; ON EXIT:	NONE						:	
  3312                              <1> ; REGISTERS ALTERED: AX						:
  3313                              <1> ;----------------------------------------------------------------		
  3314                              <1> SEND_SPEC_MD:
  3315 00001C02 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3316 00001C03 B8[201C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3317 00001C08 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3318 00001C09 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3319 00001C0B E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3320 00001C10 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3321 00001C12 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3322 00001C17 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3323 00001C1A E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3324 00001C1F 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3325                              <1> SPEC_ESBAC:
  3326 00001C20 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3327 00001C21 C3                  <1> 	RETn
  3328                              <1> 
  3329                              <1> ;-------------------------------------------------------------------------------
  3330                              <1> ; XLAT_NEW  
  3331                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3332                              <1> ;	MODE TO NEW ARCHITECTURE.
  3333                              <1> ;
  3334                              <1> ; ON ENTRY:	DI = DRIVE #
  3335                              <1> ;-------------------------------------------------------------------------------
  3336                              <1> XLAT_NEW:
  3337 00001C22 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3338 00001C25 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3339 00001C27 80BF[29710000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3340 00001C2E 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3341 00001C30 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3342 00001C33 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3343 00001C36 A0[28710000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3344 00001C3B D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3345 00001C3D 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3346 00001C3F 80A7[29710000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3347 00001C46 0887[29710000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3348                              <1> XN_OUT:
  3349 00001C4C C3                  <1> 	RETn
  3350                              <1> DO_DET:
  3351 00001C4D E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3352 00001C52 C3                  <1> 	RETn
  3353                              <1> 
  3354                              <1> ;-------------------------------------------------------------------------------
  3355                              <1> ; XLAT_OLD 
  3356                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3357                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3358                              <1> ;
  3359                              <1> ; ON ENTRY:	DI = DRIVE
  3360                              <1> ;-------------------------------------------------------------------------------
  3361                              <1> XLAT_OLD:
  3362 00001C53 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3363                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3364                              <1>         ;ja	XO_OUT
  3365                              <1>         ; 05/12/2021
  3366 00001C56 77F4                <1> 	ja	short XN_OUT
  3367 00001C58 80BF[29710000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3368 00001C5F 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3369                              <1> 
  3370                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3371                              <1> 
  3372 00001C61 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3373 00001C64 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3374 00001C67 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3375 00001C69 D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3376 00001C6B 8425[28710000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3377 00001C71 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3378                              <1> 
  3379                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3380                              <1> 
  3381 00001C73 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3382 00001C75 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3383 00001C77 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3384 00001C79 2025[28710000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3385                              <1> 
  3386                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3387                              <1> 
  3388 00001C7F 8A87[29710000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3389 00001C85 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3390 00001C87 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3391 00001C89 0805[28710000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3392                              <1> 
  3393                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3394                              <1> 
  3395                              <1> SAVE_SET:
  3396 00001C8F 8AA7[29710000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3397 00001C95 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3398 00001C97 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3399 00001C9A 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3400 00001C9D 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3401 00001C9F B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3402 00001CA1 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3403 00001CA4 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3404 00001CA6 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3405 00001CA9 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3406                              <1> UNKNO:
  3407 00001CAB B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3408 00001CAD EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3409                              <1> CHK_144:
  3410 00001CAF E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3411                              <1> 	;;20/02/2015
  3412                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3413 00001CB4 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3414 00001CB6 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3415 00001CB8 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3416 00001CBA B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3417 00001CBC EB0C                <1> 	JMP	SHORT TST_DET
  3418                              <1> CHK_250:
  3419 00001CBE B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3420 00001CC0 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3421 00001CC3 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3422 00001CC5 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3423 00001CC8 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3424                              <1> TST_DET:
  3425 00001CCA F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3426 00001CCD 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3427 00001CCF 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3428                              <1> AL_SET:
  3429 00001CD1 80A7[29710000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3430 00001CD8 0887[29710000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3431                              <1> XO_OUT:
  3432 00001CDE C3                  <1> 	RETn
  3433                              <1> 
  3434                              <1> ;-------------------------------------------------------------------------------
  3435                              <1> ; RD_WR_VF
  3436                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3437                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3438                              <1> ;
  3439                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3440                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3441                              <1> ;
  3442                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3443                              <1> ;-------------------------------------------------------------------------------
  3444                              <1> RD_WR_VF:
  3445                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3446 00001CDF 50                  <1> 	push	eax ; 05/12/2021
  3447 00001CE0 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3448 00001CE5 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3449                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3450 00001CEA 58                  <1> 	pop	eax ; 05/12/2021
  3451                              <1> DO_AGAIN:
  3452                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3453 00001CEB 50                  <1> 	push	eax ; 05/12/2021
  3454 00001CEC E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3455                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3456 00001CF1 58                  <1> 	pop	eax ; 05/12/2021
  3457                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3458                              <1> 	; 05/12/2021
  3459 00001CF2 7305                <1> 	jnc	short RWV
  3460 00001CF4 E9C3000000          <1> 	jmp	RWV_END
  3461                              <1> RWV:
  3462                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3463 00001CF9 50                  <1> 	push	eax ; 05/12/2021
  3464 00001CFA 8AB7[29710000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3465 00001D00 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3466 00001D03 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3467                              <1> 	;;20/02/2015
  3468                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3469 00001D08 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3470 00001D0A 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3471 00001D0C 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3472 00001D0E F687[29710000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3473 00001D15 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3474 00001D17 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3475 00001D19 EB0F                <1> 	JMP	SHORT RWV_2
  3476                              <1> RWV_1:
  3477 00001D1B 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3478 00001D1D F687[29710000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3479 00001D24 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3480 00001D26 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3481 00001D28 EB04                <1> 	jmp	short rwv_3
  3482                              <1> RWV_2:
  3483 00001D2A 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3484 00001D2C 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3485                              <1> rwv_3:
  3486 00001D2E E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3487 00001D33 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3488                              <1> 
  3489                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3490                              <1> 
  3491 00001D35 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3492 00001D36 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3493 00001D38 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3494                              <1> RWV_DR_SEARCH:
  3495 00001D3D 8AA3[0C6B0000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3496 00001D43 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3497 00001D46 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3498 00001D48 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3499                              <1> RWV_DR_FND:
  3500 00001D4A 8BBB[0D6B0000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3501                              <1> RWV_MD_SEARH:
  3502 00001D50 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3503 00001D53 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3504                              <1> RWV_NXT_MD:
  3505                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3506 00001D55 83C305              <1> 	add	eBX, 5
  3507 00001D58 E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3508 00001D5A 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3509                              <1> 
  3510                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3511                              <1> 
  3512                              <1> RWV_ASSUME:
  3513 00001D5B BB[2A6B0000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3514 00001D60 F687[29710000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3515 00001D67 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3516 00001D69 BB[446B0000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3517 00001D6E EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3518                              <1> 
  3519                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3520                              <1> 	 			
  3521                              <1> RWV_MD_FND:
  3522 00001D70 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3523 00001D72 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3524                              <1> 	
  3525                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3526                              <1> 
  3527                              <1> RWV_MD_FND1:
  3528 00001D73 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3529 00001D78 E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3530 00001D7D 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3531 00001D7F E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3532                              <1> RWV_DBL:
  3533 00001D84 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3534 00001D85 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3535 00001D8A 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3536 00001D8B 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3537                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3538 00001D8D 58                  <1> 	pop	eax ; 05/12/2021
  3539                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3540 00001D8E 50                  <1> 	push	eax ; 05/12/2021
  3541 00001D8F 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3542 00001D90 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3543 00001D95 5B                  <1> 	POP	eBX 
  3544                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3545 00001D96 58                  <1> 	pop	eax ; 05/12/2021
  3546 00001D97 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3547                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3548 00001D99 50                  <1> 	push	eax ; 05/12/2021
  3549 00001D9A 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3550 00001D9B E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3551 00001DA0 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3552 00001DA1 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3553 00001DA3 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3554 00001DA8 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3555 00001DAA E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3556                              <1> CHK_RET:
  3557 00001DAF E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3558                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3559 00001DB4 58                  <1> 	pop	eax ; 05/12/2021
  3560 00001DB5 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3561 00001DB7 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3562                              <1> RWV_END:
  3563 00001DBC E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3564 00001DC1 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3565                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3566                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3567 00001DC6 50                  <1> 	push	eax ; 05/12/2021
  3568 00001DC7 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3569                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3570 00001DCC 58                  <1> 	pop	eax ; 05/12/2021
  3571 00001DCD E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3572 00001DD2 C3                  <1> 	RETn
  3573                              <1> 
  3574                              <1> ;-------------------------------------------------------------------------------
  3575                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3576                              <1> ;-------------------------------------------------------------------------------
  3577                              <1> SETUP_STATE:
  3578 00001DD3 F687[29710000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3579 00001DDA 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3580 00001DDC 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3581 00001DE0 F687[29710000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3582 00001DE7 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3583 00001DE9 F687[29710000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3584 00001DF0 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3585 00001DF2 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3586                              <1> AX_SET:	
  3587 00001DF6 80A7[29710000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3588 00001DFD 08A7[29710000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3589 00001E03 8025[24710000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3590 00001E0A C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3591 00001E0D 0805[24710000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3592                              <1> J1C:	
  3593 00001E13 C3                  <1> 	RETn
  3594                              <1> 
  3595                              <1> ;-------------------------------------------------------------------------------
  3596                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3597                              <1> ;-------------------------------------------------------------------------------
  3598                              <1> FMT_INIT:
  3599 00001E14 F687[29710000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3600 00001E1B 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3601 00001E1D E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3602                              <1> 	;; 20/02/2015
  3603                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3604 00001E22 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3605 00001E24 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3606                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3607 00001E26 8AA7[29710000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3608 00001E2C 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3609 00001E2F 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3610 00001E31 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3611 00001E33 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3612 00001E36 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3613                              <1> N_360:	
  3614 00001E38 FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3615 00001E3A 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3616                              <1> F1_RATE:
  3617 00001E3C 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3618 00001E3F EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3619                              <1> N_12:	
  3620 00001E41 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3621 00001E43 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3622 00001E45 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3623 00001E48 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3624 00001E4A F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3625 00001E4D 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3626 00001E4F 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3627 00001E52 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3628                              <1> N_720:
  3629 00001E54 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3630 00001E56 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3631 00001E58 EBE2                <1> 	JMP	SHORT F1_RATE
  3632                              <1> ISNT_12: 
  3633 00001E5A 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3634                              <1> 
  3635                              <1> SKP_STATE:
  3636 00001E5D 88A7[29710000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3637                              <1> F1_OUT:
  3638 00001E63 C3                  <1> 	RETn
  3639                              <1> CL_DRV:	
  3640 00001E64 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3641 00001E66 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3642                              <1> 
  3643                              <1> ;-------------------------------------------------------------------------------
  3644                              <1> ; MED_CHANGE	
  3645                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3646                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3647                              <1> ;
  3648                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3649                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3650                              <1> ;-------------------------------------------------------------------------------
  3651                              <1> MED_CHANGE:
  3652 00001E68 E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3653 00001E6D 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3654 00001E6F 80A7[29710000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3655                              <1> 
  3656                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3657                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3658                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3659                              <1> 
  3660 00001E76 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3661 00001E79 B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3662 00001E7B D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3663 00001E7D F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3664 00001E7F FA                  <1> 	CLI				; NO INTERRUPTS
  3665 00001E80 2005[1A710000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3666 00001E86 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3667 00001E87 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3668                              <1> 
  3669                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3670                              <1> 
  3671 00001E8C E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3672 00001E91 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3673 00001E93 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3674 00001E98 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3675 00001E9A E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3676 00001E9F C605[1C710000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3677                              <1> OK1:
  3678 00001EA6 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3679 00001EAB 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3680                              <1> OK4:
  3681 00001EAD C605[1C710000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3682                              <1> OK2:		
  3683 00001EB4 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3684 00001EB5 C3                  <1> 	RETn
  3685                              <1> MC_OUT:
  3686 00001EB6 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3687 00001EB7 C3                  <1> 	RETn
  3688                              <1> 
  3689                              <1> ;-------------------------------------------------------------------------------
  3690                              <1> ; SEND_RATE
  3691                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3692                              <1> ; ON ENTRY:	DI = DRIVE #
  3693                              <1> ; ON EXIT:	NONE
  3694                              <1> ; REGISTERS ALTERED: DX
  3695                              <1> ;-------------------------------------------------------------------------------
  3696                              <1> SEND_RATE:
  3697                              <1> 	;PUSH	AX			; SAVE REG.
  3698                              <1> 	; 05/12/2021
  3699 00001EB8 50                  <1> 	push	eax
  3700 00001EB9 8025[24710000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3701 00001EC0 8A87[29710000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3702 00001EC6 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3703 00001EC8 0805[24710000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3704 00001ECE C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3705 00001ED1 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3706 00001ED5 EE                  <1> 	OUT	DX,AL
  3707                              <1> 	;POP	AX			; RESTORE REG.
  3708                              <1> 	; 05/12/2021
  3709 00001ED6 58                  <1> 	pop	eax
  3710 00001ED7 C3                  <1> 	RETn
  3711                              <1> 
  3712                              <1> ;-------------------------------------------------------------------------------
  3713                              <1> ; CHK_LASTRATE
  3714                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3715                              <1> ; ON ENTRY:
  3716                              <1> ;	DI = DRIVE #
  3717                              <1> ; ON EXIT:
  3718                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3719                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3720                              <1> ; REGISTERS ALTERED: DX
  3721                              <1> ;-------------------------------------------------------------------------------
  3722                              <1> CHK_LASTRATE:
  3723                              <1> 	;PUSH	AX			; SAVE REG.
  3724                              <1> 	; 05/12/2021
  3725 00001ED8 50                  <1> 	push	eax
  3726 00001ED9 2225[24710000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3727 00001EDF 8A87[29710000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3728 00001EE5 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3729 00001EE9 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3730                              <1> 					; ZF = 1 RATE IS THE SAME
  3731                              <1> 	;POP	AX			; RESTORE REG.
  3732                              <1> 	; 05/12/2021
  3733 00001EEB 58                  <1> 	pop	eax
  3734 00001EEC C3                  <1> 	RETn
  3735                              <1> 
  3736                              <1> ;-------------------------------------------------------------------------------
  3737                              <1> ; DMA_SETUP
  3738                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3739                              <1> ;
  3740                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3741                              <1> ;
  3742                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3743                              <1> ;-------------------------------------------------------------------------------
  3744                              <1> 
  3745                              <1> ; SI = Head #, # of Sectors or DASD Type
  3746                              <1> 
  3747                              <1> ; 22/08/2015
  3748                              <1> ; 08/02/2015 - Protected Mode Modification
  3749                              <1> ; 06/02/2015 - 07/02/2015
  3750                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3751                              <1> ; (DMA Addres = Physical Address)
  3752                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3753                              <1> ;
  3754                              <1> ; 04/02/2016 (clc)
  3755                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3756                              <1> ; 16/12/2014 (IODELAY)
  3757                              <1> 
  3758                              <1> DMA_SETUP:
  3759                              <1> 
  3760                              <1> ;; 20/02/2015
  3761 00001EED 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3762 00001EF0 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3763 00001EF6 7569                <1> 	jnz	short dma_bnd_err_stc
  3764                              <1> 	;
  3765                              <1> 	;push	ax			; DMA command
  3766                              <1> 	; 05/12/2021
  3767 00001EF8 50                  <1> 	push	eax
  3768 00001EF9 52                  <1> 	push	edx			; *
  3769 00001EFA B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3770 00001EFC E840030000          <1> 	call	GET_PARM		; 
  3771 00001F01 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3772                              <1> 	;mov	ax, si			; Sector count
  3773                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3774                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3775                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3776                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3777                              <1> 	; 05/12/2021
  3778 00001F03 89F2                <1> 	mov	edx, esi
  3779 00001F05 29C0                <1> 	sub	eax, eax
  3780 00001F07 88D4                <1> 	mov	ah, dl
  3781 00001F09 D1E8                <1> 	shr	eax, 1
  3782 00001F0B D3E0                <1> 	shl	eax, cl
  3783                              <1> 	;
  3784 00001F0D 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3785 00001F0F 6689C1              <1> 	mov	cx, ax
  3786 00001F12 5A                  <1> 	pop	edx			; *
  3787                              <1> 	;pop	ax
  3788                              <1> 	; 05/12/2021
  3789 00001F13 58                  <1> 	pop	eax
  3790 00001F14 3C42                <1> 	cmp	al, 42h
  3791 00001F16 7507                <1>         jne     short NOT_VERF
  3792 00001F18 BA0000FF00          <1> 	mov	edx, 0FF0000h
  3793 00001F1D EB08                <1> 	jmp	short J33
  3794                              <1> NOT_VERF:
  3795 00001F1F 6601CA              <1> 	add	dx, cx			; check for overflow
  3796 00001F22 723E                <1> 	jc	short dma_bnd_err
  3797                              <1> 	;
  3798 00001F24 6629CA              <1> 	sub	dx, cx			; Restore start address
  3799                              <1> J33:
  3800 00001F27 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3801 00001F28 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3802                              <1> 	IODELAY				; WAIT FOR I/O
  2144 00001F2A EB00                <2>  jmp short $+2
  2145 00001F2C EB00                <2>  jmp short $+2
  3803 00001F2E E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3804 00001F30 89D0                <1> 	mov	eax,edx			; Buffer address
  3805 00001F32 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3806                              <1> 	IODELAY				; WAIT FOR I/O
  2144 00001F34 EB00                <2>  jmp short $+2
  2145 00001F36 EB00                <2>  jmp short $+2
  3807 00001F38 88E0                <1> 	MOV	AL,AH
  3808 00001F3A E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3809 00001F3C C1E810              <1> 	shr	eax,16
  3810                              <1> 	IODELAY				; I/O WAIT STATE
  2144 00001F3F EB00                <2>  jmp short $+2
  2145 00001F41 EB00                <2>  jmp short $+2
  3811 00001F43 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3812                              <1> 	IODELAY
  2144 00001F45 EB00                <2>  jmp short $+2
  2145 00001F47 EB00                <2>  jmp short $+2
  3813 00001F49 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3814 00001F4C E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3815                              <1> 	IODELAY				; WAIT FOR I/O
  2144 00001F4E EB00                <2>  jmp short $+2
  2145 00001F50 EB00                <2>  jmp short $+2
  3816 00001F52 88E0                <1> 	MOV	AL,AH
  3817 00001F54 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3818                              <1> 	IODELAY
  2144 00001F56 EB00                <2>  jmp short $+2
  2145 00001F58 EB00                <2>  jmp short $+2
  3819 00001F5A FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3820 00001F5B B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3821 00001F5D E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3822                              <1> 
  3823 00001F5F F8                  <1> 	clc	; 04/02/2016
  3824 00001F60 C3                  <1> 	retn
  3825                              <1> 
  3826                              <1> dma_bnd_err_stc:
  3827 00001F61 F9                  <1> 	stc
  3828                              <1> dma_bnd_err:
  3829 00001F62 C605[1C710000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3830 00001F69 C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3831                              <1> 
  3832                              <1> ;; 16/12/2014
  3833                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3834                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3835                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3836                              <1> ;;	IODELAY
  3837                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3838                              <1> ;;	;SIODELAY
  3839                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3840                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3841                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3842                              <1> ;;      ;JMP	SHORT J33
  3843                              <1> ;;;NOT_VERF:	
  3844                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3845                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3846                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3847                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3848                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3849                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3850                              <1> ;;	;JNC	short J33
  3851                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3852                              <1> ;;;J33:
  3853                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3854                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3855                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3856                              <1> ;;	IODELAY
  3857                              <1> ;;	MOV	AL,AH
  3858                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3859                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3860                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3861                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3862                              <1> ;;	IODELAY
  3863                              <1> ;;	;AND	AL,00001111B
  3864                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3865                              <1> ;;	;SIODELAY
  3866                              <1> ;;
  3867                              <1> ;;;----- DETERMINE COUNT
  3868                              <1> ;;	sub	eax, eax ; 08/02/2015
  3869                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3870                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3871                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3872                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3873                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3874                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3875                              <1> ;;	CALL	GET_PARM		; "
  3876                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3877                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3878                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3879                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3880                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3881                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3882                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3883                              <1> ;;	IODELAY
  3884                              <1> ;;	MOV	AL, AH
  3885                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3886                              <1> ;;	;IODELAY
  3887                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3888                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3889                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3890                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3891                              <1> ;;	add	ecx, eax ; 08/02/2015
  3892                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3893                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3894                              <1> ;;	SIODELAY
  3895                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3896                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3897                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3898                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3899                              <1> ;;	jz	short NO_BAD
  3900                              <1> ;;dma_bnd_err:
  3901                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3902                              <1> ;;NO_BAD:
  3903                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3904                              <1> 
  3905                              <1> ;-------------------------------------------------------------------------------
  3906                              <1> ; FMTDMA_SET
  3907                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3908                              <1> ;
  3909                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3910                              <1> ;
  3911                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3912                              <1> ;-------------------------------------------------------------------------------
  3913                              <1> 
  3914                              <1> 	; 05/12/2021
  3915                              <1> FMTDMA_SET:
  3916                              <1> ;; 20/02/2015 modification	
  3917 00001F6A 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3918 00001F6D F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3919 00001F73 75EC                <1> 	jnz	short dma_bnd_err_stc
  3920                              <1> 	;
  3921                              <1> 	;push	dx			; *
  3922                              <1> 	; 05/12/2021
  3923 00001F75 52                  <1> 	push	edx
  3924 00001F76 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3925 00001F78 E8C4020000          <1> 	call	GET_PARM		; "
  3926                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3927                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3928                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3929                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3930                              <1> 	;mov	cx, ax
  3931                              <1> 	; 05/12/2021
  3932 00001F7D 29C9                <1> 	sub	ecx, ecx
  3933 00001F7F 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3934 00001F81 D1E1                <1> 	shl	ecx, 1
  3935 00001F83 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3936 00001F85 6649                <1> 	dec	cx
  3937                              <1> 	;pop	dx			; *
  3938                              <1> 	; 05/12/2021
  3939 00001F87 5A                  <1> 	pop	edx
  3940 00001F88 6601CA              <1> 	add	dx, cx			; check for overflow
  3941 00001F8B 72D5                <1> 	jc	short dma_bnd_err
  3942                              <1> 	;
  3943 00001F8D 6629CA              <1> 	sub	dx, cx			; Restore start address
  3944                              <1> 	;
  3945 00001F90 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3946 00001F92 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3947 00001F93 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3948                              <1> 	IODELAY				; WAIT FOR I/O
  2144 00001F95 EB00                <2>  jmp short $+2
  2145 00001F97 EB00                <2>  jmp short $+2
  3949 00001F99 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3950 00001F9B 89D0                <1> 	mov	eax,edx			; Buffer address
  3951 00001F9D E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3952                              <1> 	IODELAY				; WAIT FOR I/O
  2144 00001F9F EB00                <2>  jmp short $+2
  2145 00001FA1 EB00                <2>  jmp short $+2
  3953 00001FA3 88E0                <1> 	MOV	AL,AH
  3954 00001FA5 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3955 00001FA7 C1E810              <1> 	shr	eax,16
  3956                              <1> 	IODELAY				; I/O WAIT STATE
  2144 00001FAA EB00                <2>  jmp short $+2
  2145 00001FAC EB00                <2>  jmp short $+2
  3957 00001FAE E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3958                              <1> 	IODELAY
  2144 00001FB0 EB00                <2>  jmp short $+2
  2145 00001FB2 EB00                <2>  jmp short $+2
  3959 00001FB4 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3960 00001FB7 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3961                              <1> 	IODELAY				; WAIT FOR I/O
  2144 00001FB9 EB00                <2>  jmp short $+2
  2145 00001FBB EB00                <2>  jmp short $+2
  3962 00001FBD 88E0                <1> 	MOV	AL,AH
  3963 00001FBF E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3964                              <1> 	IODELAY
  2144 00001FC1 EB00                <2>  jmp short $+2
  2145 00001FC3 EB00                <2>  jmp short $+2
  3965 00001FC5 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3966 00001FC6 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3967 00001FC8 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3968 00001FCA C3                  <1> 	retn
  3969                              <1> 
  3970                              <1> ;; 08/02/2015 - Protected Mode Modification
  3971                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3972                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3973                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3974                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3975                              <1> ;;	IODELAY
  3976                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3977                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3978                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3979                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3980                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3981                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3982                              <1> ;;	;JNC	short J33A
  3983                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3984                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3985                              <1> ;;;J33A:
  3986                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3987                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3988                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3989                              <1> ;;	IODELAY
  3990                              <1> ;;	MOV	AL,AH
  3991                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3992                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3993                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3994                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3995                              <1> ;;	IODELAY
  3996                              <1> ;;	;AND	AL,00001111B
  3997                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3998                              <1> ;;
  3999                              <1> ;;;----- DETERMINE COUNT
  4000                              <1> ;;	sub	eax, eax ; 08/02/2015
  4001                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  4002                              <1> ;;	CALL	GET_PARM		; "
  4003                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  4004                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  4005                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  4006                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  4007                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  4008                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  4009                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4010                              <1> ;;	IODELAY
  4011                              <1> ;;	MOV	AL, AH
  4012                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  4013                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  4014                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  4015                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  4016                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  4017                              <1> ;;	add	ecx, eax ; 08/02/2015
  4018                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  4019                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4020                              <1> ;;	SIODELAY
  4021                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  4022                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  4023                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  4024                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  4025                              <1> ;;	jz	short FMTDMA_OK
  4026                              <1> ;;	stc	; 20/02/2015
  4027                              <1> ;;fmtdma_bnd_err:
  4028                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  4029                              <1> ;;FMTDMA_OK:
  4030                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  4031                              <1> 
  4032                              <1> ;-------------------------------------------------------------------------------
  4033                              <1> ; NEC_INIT	
  4034                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  4035                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  4036                              <1> ;
  4037                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  4038                              <1> ;
  4039                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4040                              <1> ;-------------------------------------------------------------------------------
  4041                              <1> NEC_INIT:
  4042                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4043                              <1> 	; 05/12/2021
  4044 00001FCB 50                  <1> 	push	eax
  4045 00001FCC E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4046                              <1> 
  4047                              <1> ;-----	DO THE SEEK OPERATION
  4048                              <1> 
  4049 00001FD1 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4050 00001FD4 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4051                              <1> 	;POP	AX			; RECOVER COMMAND
  4052                              <1> 	; 05/12/2021
  4053 00001FD9 58                  <1> 	pop	eax
  4054 00001FDA 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4055 00001FDC BB[FA1F0000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4056 00001FE1 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4057                              <1> 
  4058                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4059                              <1> 
  4060 00001FE2 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4061 00001FE7 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4062 00001FEA 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4063 00001FEC C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4064 00001FEF 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4065 00001FF2 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4066 00001FF4 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4067 00001FF9 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4068                              <1> ER_1:
  4069 00001FFA C3                  <1> 	RETn
  4070                              <1> 
  4071                              <1> ;-------------------------------------------------------------------------------
  4072                              <1> ; RWV_COM
  4073                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4074                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4075                              <1> ;
  4076                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4077                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4078                              <1> ;-------------------------------------------------------------------------------
  4079                              <1> RWV_COM:
  4080 00001FFB B8[46200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4081 00002000 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4082 00002001 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4083 00002004 E83E030000          <1> 	CALL	NEC_OUTPUT
  4084 00002009 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4085 0000200C E836030000          <1> 	CALL	NEC_OUTPUT
  4086 00002011 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4087 00002014 E82E030000          <1> 	CALL	NEC_OUTPUT
  4088 00002019 B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4089 0000201B E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4090 00002020 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4091 00002025 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4092 00002027 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4093 0000202C E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4094 00002031 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4095                              <1> _R15:
  4096 00002034 E80E030000          <1> 	CALL	NEC_OUTPUT
  4097 00002039 B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4098 0000203B E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4099 00002040 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4100 00002045 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4101                              <1> ER_2:
  4102 00002046 C3                  <1> 	RETn
  4103                              <1> 
  4104                              <1> ;-------------------------------------------------------------------------------
  4105                              <1> ; NEC_TERM
  4106                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4107                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4108                              <1> ;
  4109                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4110                              <1> ;-------------------------------------------------------------------------------
  4111                              <1> NEC_TERM:
  4112                              <1> 
  4113                              <1> ;-----	LET THE OPERATION HAPPEN
  4114                              <1> 
  4115 00002047 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4116 00002048 E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4117 0000204D 9C                  <1> 	PUSHFd	; 05/12/2021
  4118 0000204E E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4119 00002053 724B                <1> 	JC	short SET_END_POP
  4120 00002055 9D                  <1> 	POPFd	; 05/12/2021
  4121 00002056 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4122                              <1> 
  4123                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4124                              <1> 
  4125 00002058 FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4126 00002059 BE[1D710000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4127 0000205E AC                  <1> 	lodsb				; GET ST0
  4128 0000205F 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4129 00002061 7433                <1> 	JZ	short SET_END
  4130 00002063 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4131 00002065 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4132                              <1> 
  4133                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4134                              <1> 
  4135 00002067 AC                  <1> 	lodsb				; GET ST1
  4136 00002068 D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4137 0000206A B404                <1> 	MOV	AH,RECORD_NOT_FND
  4138 0000206C 7222                <1> 	JC	short J19
  4139 0000206E C0E002              <1> 	SAL	AL,2
  4140 00002071 B410                <1> 	MOV	AH,BAD_CRC
  4141 00002073 721B                <1> 	JC	short J19
  4142 00002075 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4143 00002077 B408                <1> 	MOV	AH,BAD_DMA
  4144 00002079 7215                <1> 	JC	short J19
  4145 0000207B C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4146 0000207E B404                <1> 	MOV	AH,RECORD_NOT_FND
  4147 00002080 720E                <1> 	JC	short J19
  4148 00002082 D0E0                <1> 	SAL	AL,1
  4149 00002084 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4150 00002086 7208                <1> 	JC	short J19
  4151 00002088 D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4152 0000208A B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4153 0000208C 7202                <1> 	JC	short J19
  4154                              <1> 
  4155                              <1> ;----- 	NEC MUST HAVE FAILED
  4156                              <1> J18:
  4157 0000208E B420                <1> 	MOV	AH,BAD_NEC
  4158                              <1> J19:
  4159 00002090 0825[1C710000]      <1> 	OR	[DSKETTE_STATUS],AH
  4160                              <1> SET_END:
  4161 00002096 803D[1C710000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4162 0000209D F5                  <1> 	CMC
  4163 0000209E 5E                  <1> 	POP	eSI
  4164 0000209F C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4165                              <1> 
  4166                              <1> SET_END_POP:
  4167 000020A0 9D                  <1> 	POPFd	; 05/12/2021
  4168 000020A1 EBF3                <1> 	JMP	SHORT SET_END
  4169                              <1> 
  4170                              <1> ;-------------------------------------------------------------------------------
  4171                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4172                              <1> ;-------------------------------------------------------------------------------
  4173                              <1> DSTATE:
  4174 000020A3 803D[1C710000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4175 000020AA 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4176 000020AC 808F[29710000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4177 000020B3 F687[29710000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4178 000020BA 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4179 000020BC 8A87[29710000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4180 000020C2 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4181 000020C4 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4182 000020C6 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4183                              <1> 
  4184                              <1> ;----- 	CHECK IF IT IS 1.44M
  4185                              <1> 
  4186 000020C8 E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4187                              <1> 	;;20/02/2015
  4188                              <1> 	;;JC	short M_12		; CMOS BAD
  4189 000020CD 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4190 000020CF 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4191 000020D1 7410                <1> 	JE	short M_12		; YES
  4192                              <1> M_720:
  4193 000020D3 80A7[29710000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4194 000020DA 808F[29710000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4195 000020E1 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4196                              <1> M_12:	
  4197 000020E3 808F[29710000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4198                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4199                              <1> SETBAC:
  4200 000020EA C3                  <1> 	RETn
  4201                              <1> 
  4202                              <1> ;-------------------------------------------------------------------------------
  4203                              <1> ; RETRY	
  4204                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4205                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4206                              <1> ;
  4207                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4208                              <1> ;-------------------------------------------------------------------------------
  4209                              <1> RETRY:
  4210 000020EB 803D[1C710000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4211 000020F2 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4212 000020F4 803D[1C710000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4213 000020FB 743C                <1> 	JZ	short NO_RETRY
  4214 000020FD 8AA7[29710000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4215 00002103 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4216 00002106 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4217 00002108 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4218 0000210B 8A2D[24710000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4219 00002111 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4220 00002114 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4221 00002117 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4222 00002119 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4223                              <1> 
  4224                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4225                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4226                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4227                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4228                              <1> 
  4229 0000211B 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4230 0000211E D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4231 00002120 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4232 00002123 80A7[29710000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4233                              <1> 					; RATE, DBL STEP OFF
  4234 0000212A 08A7[29710000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4235 00002130 C605[1C710000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4236 00002137 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4237 00002138 C3                  <1> 	RETn				; RETRY RETURN
  4238                              <1> 
  4239                              <1> NO_RETRY:
  4240 00002139 F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4241 0000213A C3                  <1> 	RETn				; NO RETRY RETURN
  4242                              <1> 
  4243                              <1> ;-------------------------------------------------------------------------------
  4244                              <1> ; NUM_TRANS
  4245                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4246                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4247                              <1> ;
  4248                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4249                              <1> ;		SI-HI  = HEAD
  4250                              <1> ;		[BP]   = START SECTOR
  4251                              <1> ;
  4252                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4253                              <1> ;-------------------------------------------------------------------------------
  4254                              <1> NUM_TRANS:
  4255 0000213B 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4256 0000213D 803D[1C710000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4257                              <1> 	; 05/12/2021
  4258 00002144 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4259 00002146 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4260 00002148 E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4261 0000214D 8A1D[22710000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4262 00002153 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4263 00002156 3A2D[21710000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4264 0000215C 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4265 0000215E 8A2D[20710000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4266 00002164 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4267 00002167 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4268 00002169 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4269                              <1> DIF_HD:
  4270 0000216B 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4271                              <1> SAME_TRK:
  4272 0000216D 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4273 00002170 88D8                <1> 	MOV	AL,BL			; TO AL
  4274                              <1> NT_OUT:
  4275 00002172 C3                  <1> 	RETn
  4276                              <1> 
  4277                              <1> ;-------------------------------------------------------------------------------
  4278                              <1> ; SETUP_END
  4279                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4280                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4281                              <1> ;
  4282                              <1> ; ON EXIT:
  4283                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4284                              <1> ;-------------------------------------------------------------------------------
  4285                              <1> SETUP_END:
  4286 00002173 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4287                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4288 00002175 50                  <1> 	push	eax ; 05/12/2021
  4289 00002176 E8C6000000          <1> 	CALL	GET_PARM
  4290 0000217B 8825[1B710000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4291                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4292 00002181 58                  <1> 	pop	eax ; 05/12/2021
  4293 00002182 8A25[1C710000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4294 00002188 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4295 0000218A 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4296 0000218C 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4297                              <1> NUN_ERR: 
  4298 0000218E 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4299 00002191 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4300 00002192 C3                  <1> 	RETn
  4301                              <1> 
  4302                              <1> ;-------------------------------------------------------------------------------
  4303                              <1> ; SETUP_DBL
  4304                              <1> ;	CHECK DOUBLE STEP.
  4305                              <1> ;
  4306                              <1> ; ON ENTRY :	DI = DRIVE
  4307                              <1> ;
  4308                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4309                              <1> ;-------------------------------------------------------------------------------
  4310                              <1> SETUP_DBL:
  4311 00002193 8AA7[29710000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4312 00002199 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4313 0000219C 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4314                              <1> 
  4315                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4316                              <1> 
  4317 0000219E C605[19710000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4318 000021A5 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4319 000021AA B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4320 000021AC E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4321 000021B1 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4322 000021B6 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4323                              <1> 
  4324                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4325                              <1> 
  4326 000021B8 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4327 000021BC F687[29710000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4328 000021C3 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4329 000021C5 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4330                              <1> 
  4331                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4332                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4333                              <1> ;	THEN SET DOUBLE STEP ON.
  4334                              <1> 
  4335                              <1> CNT_OK:
  4336 000021C7 C605[1B710000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4337                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4338                              <1> 	; 05/12/2021
  4339 000021CE 51                  <1> 	push	ecx
  4340 000021CF C605[1C710000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4341 000021D6 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4342 000021D9 D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4343 000021DB C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4344                              <1> 	;PUSH	AX			; SAVE HEAD
  4345                              <1> 	; 05/12/2021
  4346 000021DE 50                  <1> 	push	eax
  4347 000021DF E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4348                              <1> 	;POP	AX			; RESTORE HEAD
  4349                              <1> 	; 05/12/2021
  4350 000021E4 58                  <1> 	pop	eax
  4351 000021E5 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4352 000021E8 E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4353 000021ED 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4354 000021EE 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4355 000021F3 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4356                              <1> 	;POP	CX			; RESTORE COUNT
  4357                              <1> 	; 05/12/2021
  4358 000021F4 59                  <1> 	pop	ecx
  4359 000021F5 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4360 000021F7 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4361 000021F9 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4362 000021FB 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4363                              <1> 
  4364                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4365                              <1> 
  4366                              <1> SD_ERR:	
  4367 000021FD F9                  <1> 	STC				; SET CARRY FOR ERROR
  4368 000021FE C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4369                              <1> 
  4370                              <1> DO_CHK:
  4371 000021FF 8A0D[20710000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4372 00002205 888F[2D710000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4373 0000220B D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4374 0000220D 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4375 0000220F 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4376 00002211 808F[29710000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4377                              <1> NO_DBL:
  4378 00002218 F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4379 00002219 C3                  <1> 	RETn
  4380                              <1> 
  4381                              <1> ;-------------------------------------------------------------------------------
  4382                              <1> ; READ_ID
  4383                              <1> ;	READ ID FUNCTION.
  4384                              <1> ;
  4385                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4386                              <1> ;
  4387                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4388                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4389                              <1> ;-------------------------------------------------------------------------------
  4390                              <1> READ_ID:
  4391 0000221A B8[37220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4392 0000221F 50                  <1> 	PUSH	eAX
  4393 00002220 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4394 00002222 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4395 00002227 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4396 0000222A 88C4                <1> 	MOV	AH,AL
  4397 0000222C E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4398 00002231 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4399 00002236 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4400                              <1> ER_3:
  4401 00002237 C3                  <1> 	RETn
  4402                              <1> 
  4403                              <1> ;-------------------------------------------------------------------------------
  4404                              <1> ; CMOS_TYPE
  4405                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4406                              <1> ;
  4407                              <1> ; ON ENTRY:	DI = DRIVE #
  4408                              <1> ;
  4409                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4410                              <1> ;-------------------------------------------------------------------------------
  4411                              <1> 
  4412                              <1> CMOS_TYPE: ; 11/12/2014
  4413 00002238 8A87[8E6B0000]      <1> 	mov	al, [eDI+fd0_type]
  4414 0000223E 20C0                <1> 	and 	al, al ; 18/12/2014
  4415 00002240 C3                  <1> 	retn
  4416                              <1> 
  4417                              <1> ;CMOS_TYPE:
  4418                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4419                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4420                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4421                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4422                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4423                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4424                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4425                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4426                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4427                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4428                              <1> ;TB:
  4429                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4430                              <1> ;BAD_CM:
  4431                              <1> ;	RETn				; CY, STATUS OF READ
  4432                              <1> 
  4433                              <1> ;-------------------------------------------------------------------------------
  4434                              <1> ; GET_PARM
  4435                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4436                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4437                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4438                              <1> ;	THE PARAMETER IN DL.
  4439                              <1> ;
  4440                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4441                              <1> ;
  4442                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4443                              <1> ;		AL,DH DESTROYED
  4444                              <1> ;-------------------------------------------------------------------------------
  4445                              <1> GET_PARM:
  4446                              <1> 	;PUSH	DS
  4447 00002241 56                  <1> 	PUSH	eSI
  4448                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4449                              <1>     	;MOV	DS,AX
  4450                              <1> 	;;mov	ax, cs
  4451                              <1> 	;;mov	ds, ax
  4452                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4453 00002242 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4454                              <1> 	;SUB	BH,BH			; BX = INDEX
  4455 00002244 81E3FF000000        <1> 	and	ebx, 0FFh
  4456                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4457                              <1> 	;
  4458                              <1> 	; 17/12/2014
  4459 0000224A 66A1[816B0000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4460 00002250 38E0                <1> 	cmp	al, ah
  4461 00002252 7425                <1> 	je	short gpndc
  4462 00002254 A2[826B0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4463 00002259 53                  <1> 	push	ebx ; 08/02/2015
  4464 0000225A 88C3                <1> 	mov	bl, al 
  4465                              <1> 	; 11/12/2014
  4466 0000225C 8A83[8E6B0000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4467                              <1> 	; 18/12/2014
  4468 00002262 20C0                <1> 	and	al, al
  4469 00002264 7507                <1> 	jnz	short gpdtc
  4470 00002266 BB[6B6B0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4471 0000226B EB05                <1>         jmp     short gpdpu
  4472                              <1> gpdtc:	
  4473 0000226D E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4474                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4475                              <1> gpdpu:
  4476 00002272 891D[086B0000]      <1> 	mov	[DISK_POINTER], ebx
  4477 00002278 5B                  <1> 	pop	ebx
  4478                              <1> gpndc:
  4479 00002279 8B35[086B0000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4480 0000227F 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4481 00002282 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4482 00002284 5E                  <1> 	POP	eSI
  4483                              <1> 	;POP	DS
  4484 00002285 C3                  <1> 	RETn
  4485                              <1> 
  4486                              <1> ;-------------------------------------------------------------------------------
  4487                              <1> ; MOTOR_ON
  4488                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4489                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4490                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4491                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4492                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4493                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4494                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4495                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4496                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4497                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4498                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4499                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4500                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4501                              <1> ;
  4502                              <1> ; ON ENTRY:	DI = DRIVE #
  4503                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4504                              <1> ;-------------------------------------------------------------------------------
  4505                              <1> MOTOR_ON:
  4506 00002286 53                  <1> 	PUSH	eBX			; SAVE REG.
  4507 00002287 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4508 0000228C 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4509 0000228E E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4510 00002293 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4511                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4512                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4513                              <1> M_WAIT:
  4514 00002298 B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4515 0000229A E8A2FFFFFF          <1> 	CALL	GET_PARM
  4516                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4517                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4518                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4519 0000229F 80FC08              <1> 	cmp	ah, 8
  4520                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4521 000022A2 7702                <1> 	ja	short J13
  4522                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4523 000022A4 B408                <1> 	mov	ah, 8
  4524                              <1> 
  4525                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4526                              <1> GP2:	
  4527                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4528                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4529 000022A6 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4530 000022AB E80BF2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4531                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4532 000022B0 FECC                <1> 	dec	ah
  4533 000022B2 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4534                              <1> MOT_IS_ON:
  4535 000022B4 5B                  <1> 	POP	eBX			; RESTORE REG.
  4536 000022B5 C3                  <1> 	RETn
  4537                              <1> 
  4538                              <1> ;-------------------------------------------------------------------------------
  4539                              <1> ; TURN_ON
  4540                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4541                              <1> ;
  4542                              <1> ; ON ENTRY:	DI = DRIVE #
  4543                              <1> ;
  4544                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4545                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4546                              <1> ;		AX,BX,CX,DX DESTROYED
  4547                              <1> ;-------------------------------------------------------------------------------
  4548                              <1> TURN_ON:
  4549 000022B6 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4550 000022B8 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4551 000022BA C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4552 000022BD FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4553 000022BE C605[1B710000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4554 000022C5 A0[1A710000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4555 000022CA 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4556 000022CC B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4557 000022CE D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4558                              <1> 
  4559                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4560                              <1> ;  BL = DRIVE SELECT DESIRED
  4561                              <1> ;  AH = MOTOR ON MASK DESIRED
  4562                              <1> 
  4563 000022D0 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4564 000022D2 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4565 000022D4 8425[1A710000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4566 000022DA 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4567                              <1> 
  4568                              <1> TURN_IT_ON:
  4569 000022DC 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4570 000022DE 8A3D[1A710000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4571 000022E4 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4572 000022E7 8025[1A710000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4573 000022EE 0825[1A710000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4574 000022F4 A0[1A710000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4575 000022F9 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4576 000022FB 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4577 000022FE FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4578 000022FF 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4579 00002301 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4580 00002304 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4581 00002306 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4582 0000230A EE                  <1> 	OUT	DX,AL
  4583 0000230B 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4584                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4585 0000230D 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4586 0000230F F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4587 00002310 C3                  <1> 	RETn
  4588                              <1> 
  4589                              <1> NO_MOT_WAIT:
  4590 00002311 FB                  <1> 	sti
  4591                              <1> no_mot_w1: ; 27/02/2015
  4592 00002312 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4593                              <1> 	;STI				; INTERRUPTS BACK ON
  4594 00002313 C3                  <1> 	RETn
  4595                              <1> 
  4596                              <1> ;-------------------------------------------------------------------------------
  4597                              <1> ; HD_WAIT
  4598                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4599                              <1> ;
  4600                              <1> ; ON ENTRY:	DI = DRIVE #
  4601                              <1> ;
  4602                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4603                              <1> ;-------------------------------------------------------------------------------
  4604                              <1> HD_WAIT:
  4605 00002314 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4606 00002316 E826FFFFFF          <1> 	CALL	GET_PARM
  4607 0000231B 08E4                <1> 	or	ah, ah	; 17/12/2014
  4608 0000231D 7519                <1> 	jnz	short DO_WAT
  4609 0000231F F605[1A710000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4610                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4611                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4612                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4613 00002326 741E                <1> 	jz	short HW_DONE
  4614 00002328 B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4615 0000232A 8A87[29710000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4616 00002330 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4617 00002332 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4618 00002334 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4619                              <1> ;GP3:
  4620 00002336 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4621                              <1> ;	JMP	SHORT DO_WAT
  4622                              <1> 
  4623                              <1> ;ISNT_WRITE:
  4624                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4625                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4626                              <1> 
  4627                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4628                              <1> DO_WAT:
  4629                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4630                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4631                              <1> J29:					; 	1 MILLISECOND LOOP
  4632                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4633 00002338 B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4634 0000233D E879F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4635                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4636 00002342 FECC                <1> 	dec	ah
  4637 00002344 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4638                              <1> HW_DONE:
  4639 00002346 C3                  <1> 	RETn
  4640                              <1> 
  4641                              <1> ;-------------------------------------------------------------------------------
  4642                              <1> ; NEC_OUTPUT
  4643                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4644                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4645                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4646                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4647                              <1> ; 
  4648                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4649                              <1> ;
  4650                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4651                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4652                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4653                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4654                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4655                              <1> ;		AX,CX,DX DESTROYED
  4656                              <1> ;-------------------------------------------------------------------------------
  4657                              <1> 
  4658                              <1> ; 09/12/2014 [Erdogan Tan] 
  4659                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4660                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4661                              <1> ;	This read only register facilitates the transfer of data between
  4662                              <1> ;	the system microprocessor and the controller.
  4663                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4664                              <1> ;	  with the system micrprocessor.
  4665                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4666                              <1> ;	  the transfer is to the controller.
  4667                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4668                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4669                              <1> ; Bit 3 - Reserved.
  4670                              <1> ; Bit 2 - Reserved.
  4671                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4672                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4673                              <1> 
  4674                              <1> ; Data Register (3F5h)
  4675                              <1> ; This read/write register passes data, commands and parameters, and provides
  4676                              <1> ; diskette status information.
  4677                              <1>   		
  4678                              <1> NEC_OUTPUT:
  4679                              <1> 	;PUSH	BX			; SAVE REG.
  4680 00002347 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4681                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4682                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4683                              <1> 	; 16/12/2014
  4684                              <1> 	; waiting for (max.) 0.5 seconds
  4685                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4686                              <1> 	;
  4687                              <1> 	; 17/12/2014
  4688                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4689                              <1> 	;
  4690                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4691                              <1> 	;		go on.
  4692                              <1> 	;INPUT:
  4693                              <1> 	;	AH=Mask for isolation bits.
  4694                              <1> 	;	AL=pattern to look for.
  4695                              <1> 	;	DX=Port to test for
  4696                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4697                              <1> 	;	     (normally 30 microseconds per period.)
  4698                              <1> 	;
  4699                              <1> 	;WFP_SHORT:  
  4700                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4701                              <1> 	;
  4702                              <1> 
  4703                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4704                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4705 0000234B B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4706                              <1> ;
  4707                              <1> ;WFPS_OUTER_LP:
  4708                              <1> ;	;
  4709                              <1> ;WFPS_CHECK_PORT:
  4710                              <1> J23:
  4711 00002350 EC                  <1> 	IN	AL,DX			; GET STATUS
  4712 00002351 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4713 00002353 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4714 00002355 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4715                              <1> WFPS_HI:
  4716 00002357 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4717 00002359 A810                <1> 	TEST	AL,010H			; transition on memory
  4718 0000235B 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4719                              <1> WFPS_LO:
  4720 0000235D E461                <1> 	IN	AL, PORT_B		; SYS1
  4721 0000235F A810                <1> 	TEST	AL,010H
  4722 00002361 74FA                <1> 	JZ	SHORT WFPS_LO
  4723                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4724 00002363 E2EB                <1> 	loop	J23	; 27/02/2015
  4725                              <1> ;	;
  4726                              <1> ;	dec	bl
  4727                              <1> ;	jnz	short WFPS_OUTER_LP
  4728                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4729                              <1> ;J23:
  4730                              <1> ;	IN	AL,DX			; GET STATUS
  4731                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4732                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4733                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4734                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4735                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4736                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4737                              <1>    
  4738                              <1> 	;;27/02/2015
  4739                              <1> 	;16/12/2014
  4740                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4741                              <1> 	;;jb	short J23
  4742                              <1> 
  4743                              <1> ;WFPS_TIMEOUT:
  4744                              <1> 
  4745                              <1> ;-----	FALL THRU TO ERROR RETURN
  4746                              <1> 
  4747 00002365 800D[1C710000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4748                              <1> 	;POP	BX			; RESTORE REG.
  4749 0000236C 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4750 0000236D F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4751 0000236E C3                  <1> 	RETn
  4752                              <1> 
  4753                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4754                              <1> 
  4755                              <1> J27:	
  4756 0000236F 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4757 00002371 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4758 00002373 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4759                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4760                              <1> 	; 27/02/2015
  4761 00002374 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE FLAGS
  4762                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4763 00002375 29C9                <1> 	sub	ecx, ecx
  4764 00002377 B103                <1> 	mov	cl, 3 ; 05/12/2021
  4765 00002379 E83DF1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4766 0000237E 9D                  <1> 	POPFd	; 05/12/2021			; RESTORE FLAGS FOR EXIT
  4767                              <1> 	;POP	BX			; RESTORE REG
  4768 0000237F C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4769                              <1> 
  4770                              <1> ;-------------------------------------------------------------------------------
  4771                              <1> ; SEEK
  4772                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4773                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4774                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4775                              <1> ;
  4776                              <1> ; ON ENTRY:	DI = DRIVE #
  4777                              <1> ;		CH = TRACK #
  4778                              <1> ;
  4779                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4780                              <1> ;		AX,BX,CX DX DESTROYED
  4781                              <1> ;-------------------------------------------------------------------------------
  4782                              <1> SEEK:
  4783 00002380 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4784 00002382 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4785 00002384 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4786 00002386 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4787 00002388 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4788 0000238A 8405[19710000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4789 00002390 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4790                              <1> 
  4791 00002392 0805[19710000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4792 00002398 E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4793 0000239D 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4794                              <1> 
  4795                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4796                              <1> 
  4797 0000239F C605[1C710000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4798 000023A6 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4799 000023AB 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4800                              <1> 
  4801                              <1> AFT_RECAL:
  4802 000023AD C687[2D710000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4803 000023B4 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4804 000023B6 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4805                              <1> 
  4806                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4807                              <1> 
  4808 000023B8 F687[29710000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4809 000023BF 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4810 000023C1 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4811                              <1> 
  4812 000023C3 3AAF[2D710000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4813 000023C9 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4814                              <1> 
  4815 000023CB BA[FE230000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4816 000023D0 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4817 000023D1 88AF[2D710000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4818 000023D7 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4819 000023D9 E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4820 000023DE 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4821 000023E0 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4822 000023E2 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4823 000023E7 8AA7[2D710000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4824 000023ED E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4825 000023F2 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4826                              <1> 
  4827                              <1> ;-----	WAIT FOR HEAD SETTLE
  4828                              <1> 
  4829                              <1> DO_WAIT:
  4830 000023F7 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE STATUS
  4831 000023F8 E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4832 000023FD 9D                  <1> 	POPFd	; 05/12/2021		; RESTORE STATUS
  4833                              <1> RB:
  4834                              <1> NEC_ERR:
  4835                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4836                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4837 000023FE C3                  <1> 	RETn				; RETURN TO CALLER
  4838                              <1> 
  4839                              <1> ;-------------------------------------------------------------------------------
  4840                              <1> ; RECAL
  4841                              <1> ;	RECALIBRATE DRIVE
  4842                              <1> ;
  4843                              <1> ; ON ENTRY:	DI = DRIVE #
  4844                              <1> ;
  4845                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4846                              <1> ;-------------------------------------------------------------------------------
  4847                              <1> RECAL:
  4848                              <1> 	;PUSH	CX
  4849                              <1> 	; 05/12/2021
  4850 000023FF 51                  <1> 	push	ecx
  4851 00002400 B8[1C240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4852 00002405 50                  <1> 	PUSH	eAX
  4853 00002406 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4854 00002408 E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4855 0000240D 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4856 0000240F 88DC                <1> 	MOV	AH,BL
  4857 00002411 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4858 00002416 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4859 0000241B 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4860                              <1> RC_BACK:
  4861                              <1> 	;POP	CX
  4862                              <1> 	; 05/12/2021
  4863 0000241C 59                  <1> 	pop	ecx
  4864 0000241D C3                  <1> 	RETn
  4865                              <1> 
  4866                              <1> ;-------------------------------------------------------------------------------
  4867                              <1> ; CHK_STAT_2
  4868                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4869                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4870                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4871                              <1> ;
  4872                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4873                              <1> ;-------------------------------------------------------------------------------
  4874                              <1> CHK_STAT_2:
  4875 0000241E B8[46240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4876 00002423 50                  <1> 	PUSH	eAX
  4877 00002424 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4878 00002429 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4879 0000242B B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4880 0000242D E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4881 00002432 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4882 00002437 720C                <1> 	JC	short J34
  4883 00002439 A0[1D710000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4884 0000243E 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4885 00002440 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4886 00002442 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4887 00002444 F8                  <1> 	CLC				; GOOD RETURN
  4888                              <1> J34:
  4889 00002445 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4890                              <1> CS_BACK:
  4891 00002446 C3                  <1> 	RETn
  4892                              <1> J35:
  4893 00002447 800D[1C710000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4894 0000244E F9                  <1> 	STC				; ERROR RETURN CODE
  4895 0000244F EBF4                <1> 	JMP	SHORT J34
  4896                              <1> 
  4897                              <1> ;-------------------------------------------------------------------------------
  4898                              <1> ; WAIT_INT
  4899                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4900                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4901                              <1> ;	IF THE DRIVE IS NOT READY.
  4902                              <1> ;
  4903                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4904                              <1> ;-------------------------------------------------------------------------------
  4905                              <1> 
  4906                              <1> ; 17/12/2014
  4907                              <1> ; 2.5 seconds waiting !
  4908                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4909                              <1> ; amount of time to wait for completion interrupt from NEC.
  4910                              <1> 
  4911                              <1> 
  4912                              <1> WAIT_INT:
  4913 00002451 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4914 00002452 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4915                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4916                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4917                              <1> 
  4918                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4919                              <1> 	;
  4920                              <1> 	;WAIT_FOR_MEM:	
  4921                              <1> 	;	Waits for a bit at a specified memory location pointed
  4922                              <1> 	;	to by ES:[DI] to become set.
  4923                              <1> 	;INPUT:
  4924                              <1> 	;	AH=Mask to test with.
  4925                              <1> 	;	ES:[DI] = memory location to watch.
  4926                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4927                              <1> 	;	     (normally 30 microseconds per period.)
  4928                              <1> 
  4929                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4930                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4931                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4932                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4933                              <1> 	; 27/02/2015
  4934 00002453 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4935                              <1> WFMS_CHECK_MEM:
  4936 00002458 F605[19710000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4937 0000245F 7516                <1>         jnz     short J37
  4938                              <1> WFMS_HI:
  4939 00002461 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4940 00002463 A810                <1> 	TEST	AL,010H			; transition on memory
  4941 00002465 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4942                              <1> WFMS_LO:
  4943 00002467 E461                <1> 	IN	AL,PORT_B		;SYS1
  4944 00002469 A810                <1> 	TEST	AL,010H
  4945 0000246B 74FA                <1> 	JZ	SHORT WFMS_LO
  4946 0000246D E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4947                              <1> ;WFMS_OUTER_LP:
  4948                              <1> ;;	or	bl, bl			; check outer counter
  4949                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4950                              <1> ;	dec	bl
  4951                              <1> ;	jz	short J36A	
  4952                              <1> ;	jmp	short WFMS_CHECK_MEM
  4953                              <1> 
  4954                              <1> 	;17/12/2014
  4955                              <1> 	;16/12/2014
  4956                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4957                              <1> ;J36:
  4958                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4959                              <1> ;	JNZ	short J37
  4960                              <1> 	;16/12/2014
  4961                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4962                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4963                              <1> 	;JNZ	short J36
  4964                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4965                              <1> ;	jb	short J36
  4966                              <1> 
  4967                              <1> ;WFMS_TIMEOUT:
  4968                              <1> ;J36A:
  4969 0000246F 800D[1C710000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4970 00002476 F9                  <1> 	STC				; ERROR RETURN
  4971                              <1> J37:
  4972 00002477 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4973 00002478 8025[19710000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4974 0000247F 9D                  <1> 	POPF				; RECOVER CARRY
  4975 00002480 C3                  <1> 	RETn				; GOOD RETURN CODE
  4976                              <1> 
  4977                              <1> ;-------------------------------------------------------------------------------
  4978                              <1> ; RESULTS
  4979                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4980                              <1> ;	FOLLOWING AN INTERRUPT.
  4981                              <1> ;
  4982                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4983                              <1> ;		AX,BX,CX,DX DESTROYED
  4984                              <1> ;-------------------------------------------------------------------------------
  4985                              <1> RESULTS:
  4986 00002481 57                  <1> 	PUSH	eDI
  4987 00002482 BF[1D710000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4988 00002487 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4989 00002489 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4990                              <1> 
  4991                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4992                              <1> 
  4993                              <1> _R10: 
  4994                              <1> 	; 16/12/2014
  4995                              <1> 	; wait for (max) 0.5 seconds
  4996                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4997                              <1> 	;XOR	CX,CX			; COUNTER
  4998                              <1> 
  4999                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  5000                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  5001                              <1> 	; 27/02/2015
  5002 0000248D B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  5003                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  5004                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  5005                              <1> 
  5006                              <1> WFPSR_OUTER_LP:
  5007                              <1> 	;
  5008                              <1> WFPSR_CHECK_PORT:
  5009                              <1> J39:					; WAIT FOR MASTER
  5010 00002492 EC                  <1> 	IN	AL,DX			; GET STATUS
  5011 00002493 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5012 00002495 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5013 00002497 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  5014                              <1> WFPSR_HI:
  5015 00002499 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  5016 0000249B A810                <1> 	TEST	AL,010H			; transition on memory
  5017 0000249D 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  5018                              <1> WFPSR_LO:
  5019 0000249F E461                <1> 	IN	AL, PORT_B		; SYS1
  5020 000024A1 A810                <1> 	TEST	AL,010H
  5021 000024A3 74FA                <1> 	JZ	SHORT WFPSR_LO
  5022 000024A5 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  5023                              <1> 	;; 27/02/2015
  5024                              <1> 	;;dec	bh
  5025                              <1> 	;;jnz	short WFPSR_OUTER_LP
  5026                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  5027                              <1> 
  5028                              <1> 	;;mov	byte [wait_count], 0
  5029                              <1> ;J39:					; WAIT FOR MASTER
  5030                              <1> ;	IN	AL,DX			; GET STATUS
  5031                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5032                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5033                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  5034                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  5035                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  5036                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  5037                              <1> 	;
  5038                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  5039                              <1> 	;;jb	short J39	
  5040                              <1> 
  5041                              <1> ;WFPSR_TIMEOUT:
  5042 000024A7 800D[1C710000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5043 000024AE F9                  <1> 	STC				; SET ERROR RETURN
  5044 000024AF EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5045                              <1> 
  5046                              <1> ;-----	READ IN THE STATUS
  5047                              <1> 
  5048                              <1> J42:
  5049 000024B1 EB00                <1> 	JMP	$+2			; I/O DELAY
  5050 000024B3 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5051 000024B5 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5052                              <1> 	; 16/12/2014
  5053                              <1> 	NEWIODELAY
  2149 000024B6 E6EB                <2>  out 0EBh,al
  5054 000024B8 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5055 000024BA 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5056                              <1> 	; 16/12/2014
  5057                              <1> ;	push	cx
  5058                              <1> ;	mov	cx, 30
  5059                              <1> ;wdw2:
  5060                              <1> ;	NEWIODELAY
  5061                              <1> ;	loop	wdw2
  5062                              <1> ;	pop	cx
  5063                              <1> 
  5064 000024BB B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5065 000024C0 E8F6EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5066 000024C5 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5067 000024C7 EC                  <1> 	IN	AL,DX			; GET STATUS
  5068                              <1> 	; 16/12/2014
  5069                              <1> 	NEWIODELAY
  2149 000024C8 E6EB                <2>  out 0EBh,al
  5070                              <1> 	;
  5071 000024CA A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5072 000024CC 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5073                              <1> 
  5074 000024CE FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5075 000024D0 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5076 000024D2 800D[1C710000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5077 000024D9 F9                  <1> 	STC				; SET ERROR FLAG
  5078                              <1> 
  5079                              <1> ;-----	RESULT OPERATION IS DONE
  5080                              <1> POPRES:
  5081 000024DA 5F                  <1> 	POP	eDI
  5082 000024DB C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5083                              <1> 
  5084                              <1> ;-------------------------------------------------------------------------------
  5085                              <1> ; READ_DSKCHNG
  5086                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5087                              <1> ;
  5088                              <1> ; ON ENTRY:	DI = DRIVE #
  5089                              <1> ;
  5090                              <1> ; ON EXIT:	DI = DRIVE #
  5091                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5092                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5093                              <1> ;		AX,CX,DX DESTROYED
  5094                              <1> ;-------------------------------------------------------------------------------
  5095                              <1> READ_DSKCHNG:
  5096 000024DC E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5097 000024E1 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5098 000024E5 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5099 000024E6 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5100 000024E8 C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5101                              <1> 
  5102                              <1> ;-------------------------------------------------------------------------------
  5103                              <1> ; DRIVE_DET
  5104                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5105                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5106                              <1> ; ON ENTRY:	DI = DRIVE #
  5107                              <1> ;-------------------------------------------------------------------------------
  5108                              <1> DRIVE_DET:
  5109 000024E9 E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5110 000024EE E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5111 000024F3 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5112 000024F5 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5113 000024F7 E884FEFFFF          <1> 	CALL	SEEK
  5114 000024FC 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5115 000024FE B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5116                              <1> SK_GIN:
  5117 00002500 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5118                              <1> 	;PUSH	CX			; SAVE TRACK
  5119                              <1> 	; 05/12/2021
  5120 00002502 51                  <1> 	push	ecx
  5121 00002503 E878FEFFFF          <1> 	CALL	SEEK
  5122 00002508 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5123 0000250A B8[45250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5124 0000250F 50                  <1> 	PUSH	eAX
  5125 00002510 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5126 00002512 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5127 00002517 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5128 0000251A 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5129 0000251C E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5130 00002521 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5131 00002526 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5132                              <1> 	;POP	CX			; RESTORE TRACK
  5133                              <1> 	; 05/12/2021
  5134 00002527 59                  <1> 	pop	ecx
  5135 00002528 F605[1D710000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5136 0000252F 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5137 00002531 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5138 00002533 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5139                              <1> 
  5140                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5141                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5142                              <1> 
  5143 00002535 808F[29710000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5144 0000253C C3                  <1> 	RETn				; ALL INFORMATION SET
  5145                              <1> IS_80:
  5146 0000253D 808F[29710000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5147                              <1> DD_BAC:
  5148 00002544 C3                  <1> 	RETn
  5149                              <1> POP_BAC:
  5150                              <1> 	;POP	CX			; THROW AWAY
  5151                              <1> 	; 05/12/2021
  5152 00002545 59                  <1> 	pop	ecx
  5153 00002546 C3                  <1> 	RETn
  5154                              <1> 
  5155                              <1> fdc_int:  
  5156                              <1> 	  ; 30/07/2015	
  5157                              <1> 	  ; 16/02/2015
  5158                              <1> ;int_0Eh: ; 11/12/2014
  5159                              <1> 
  5160                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5161                              <1> ; DISK_INT
  5162                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5163                              <1> ;
  5164                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5165                              <1> ;-------------------------------------------------------------------------------
  5166                              <1> DISK_INT_1:
  5167                              <1> 
  5168                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5169                              <1> 	; 05/12/2021
  5170 00002547 50                  <1> 	push	eax
  5171 00002548 1E                  <1> 	push	ds
  5172 00002549 66B81000            <1> 	mov	ax, KDATA
  5173 0000254D 8ED8                <1> 	mov 	ds, ax
  5174 0000254F 800D[19710000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5175 00002556 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5176 00002558 E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5177 0000255A 1F                  <1> 	pop	ds
  5178                              <1> 	;POP	AX			; RECOVER REGISTER
  5179                              <1> 	; 05/12/2021
  5180 0000255B 58                  <1> 	pop	eax
  5181 0000255C CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5182                              <1> 
  5183                              <1> ;-------------------------------------------------------------------------------
  5184                              <1> ; DSKETTE_SETUP
  5185                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5186                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5187                              <1> ;-------------------------------------------------------------------------------
  5188                              <1> DSKETTE_SETUP:
  5189                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5190                              <1> 	;PUSH	BX
  5191                              <1> 	;PUSH	CX
  5192 0000255D 52                  <1> 	PUSH	eDX
  5193                              <1> 	;PUSH	DI
  5194                              <1> 	;;PUSH	DS
  5195                              <1> 	; 14/12/2014
  5196                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5197                              <1> 	;mov	[DISK_POINTER+2], cs
  5198                              <1> 	;
  5199                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5200 0000255E 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5201 00002560 66C705[29710000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5201 00002568 00                  <1>
  5202 00002569 8025[24710000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5203 00002570 800D[24710000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5204 00002577 C605[19710000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5205 0000257E C605[1B710000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5206 00002585 C605[1A710000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5207 0000258C C605[1C710000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5208                              <1> 	;
  5209                              <1> 	; 28/02/2015
  5210                              <1> 	;mov	word [cfd], 100h 
  5211 00002593 E89DF2FFFF          <1> 	call	DSK_RESET
  5212 00002598 5A                  <1> 	pop	edx
  5213 00002599 C3                  <1> 	retn
  5214                              <1> 
  5215                              <1> ;SUP0:
  5216                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5217                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5218                              <1> ;	; 02/01/2015
  5219                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5220                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5221                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5222                              <1> ;       cmp     byte [fd1_type], 0	
  5223                              <1> ;	jna	short sup1
  5224                              <1> ;	or	di, di
  5225                              <1> ;	jnz	short sup1
  5226                              <1> ;	inc	di
  5227                              <1> ;       jmp     short SUP0
  5228                              <1> ;sup1:
  5229                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5230                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5231                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5232                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5233                              <1> ;	;POP	DI
  5234                              <1> ;	POP	eDX
  5235                              <1> ;	;POP	CX
  5236                              <1> ;	;POP	BX
  5237                              <1> ;	;POP	AX
  5238                              <1> ;	RETn
  5239                              <1> 
  5240                              <1> ;//////////////////////////////////////////////////////
  5241                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5242                              <1> ;
  5243                              <1> 
  5244                              <1> int13h: ; 21/02/2015
  5245 0000259A 9C                  <1> 	pushfd
  5246 0000259B 0E                  <1> 	push 	cs
  5247 0000259C E858000000          <1> 	call 	DISK_IO
  5248 000025A1 C3                  <1> 	retn
  5249                              <1> 
  5250                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5251                              <1> ;/////////////////////////////////////////////////////////////////////
  5252                              <1> 
  5253                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5254                              <1> ; 23/02/2015
  5255                              <1> ; 21/02/2015 (unix386.s)
  5256                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5257                              <1> ;
  5258                              <1> ; Original Source Code:
  5259                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5260                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5261                              <1> ;
  5262                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5263                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5264                              <1> ;
  5265                              <1> 
  5266                              <1> ;The wait for controller to be not busy is 10 seconds.
  5267                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5268                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5269                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5270                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5271                              <1> 
  5272                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5273                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5274                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5275                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5276                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5277                              <1> 
  5278                              <1> ;The wait for Data request on read and write longs is
  5279                              <1> ;2000 us. (?)
  5280                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5281                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5282                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5283                              <1> 
  5284                              <1> ; Port 61h (PORT_B)
  5285                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5286                              <1> 
  5287                              <1> ; 23/12/2014
  5288                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5289                              <1> 
  5290                              <1> ;--- INT 13H -------------------------------------------------------------------
  5291                              <1> ;									       :
  5292                              <1> ; FIXED DISK I/O INTERFACE						       :
  5293                              <1> ;									       :
  5294                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5295                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5296                              <1> ;									       :
  5297                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5298                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5299                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5300                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5301                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5302                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5303                              <1> ;									       :
  5304                              <1> ;------------------------------------------------------------------------------:
  5305                              <1> ;									       :
  5306                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5307                              <1> ;									       :
  5308                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5309                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5310                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5311                              <1> ;			  DL > 80H - DISK				       :
  5312                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5313                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5314                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5315                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5316                              <1> ;	(AH)= 06H  UNUSED						       :
  5317                              <1> ;	(AH)= 07H  UNUSED						       :
  5318                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5319                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5320                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5321                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5322                              <1> ;	(AH)= 0AH  READ LONG						       :
  5323                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5324                              <1> ;	(AH)= 0CH  SEEK 						       :
  5325                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5326                              <1> ;	(AH)= 0EH  UNUSED						       :
  5327                              <1> ;	(AH)= 0FH  UNUSED						       :
  5328                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5329                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5330                              <1> ;	(AH)= 12H  UNUSED						       :
  5331                              <1> ;	(AH)= 13H  UNUSED						       :
  5332                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5333                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5334                              <1> ;									       :
  5335                              <1> ;-------------------------------------------------------------------------------
  5336                              <1> ;									       :
  5337                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5338                              <1> ;									       :
  5339                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5340                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5341                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5342                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5343                              <1> ;									       :
  5344                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5345                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5346                              <1> ;				 (10 BITS TOTAL)			       :
  5347                              <1> ;									       :
  5348                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5349                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5350                              <1> ;									       :
  5351                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5352                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5353                              <1> ;									       :
  5354                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5355                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5356                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5357                              <1> ;			       80H FOR A BAD SECTOR			       :
  5358                              <1> ;			   N = SECTOR NUMBER				       :
  5359                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5360                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5361                              <1> ;									       :
  5362                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5363                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5364                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5365                              <1> ;									       :
  5366                              <1> ;-------------------------------------------------------------------------------
  5367                              <1> 
  5368                              <1> ;-------------------------------------------------------------------------------
  5369                              <1> ; OUTPUT								       :
  5370                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5371                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5372                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5373                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5374                              <1> ;									       :
  5375                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5376                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5377                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5378                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5379                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5380                              <1> ;		REWRITTEN.						       :
  5381                              <1> ;									       :
  5382                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5383                              <1> ;	   INPUT:							       :
  5384                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5385                              <1> ;	   OUTPUT:							       :
  5386                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5387                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5388                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5389                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5390                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5391                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5392                              <1> ;									       :
  5393                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5394                              <1> ;									       :
  5395                              <1> ;	AH = 0 - NOT PRESENT						       :
  5396                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5397                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5398                              <1> ;	     3 - FIXED DISK						       :
  5399                              <1> ;									       :
  5400                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5401                              <1> ;									       :
  5402                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5403                              <1> ;	INFORMATION.							       :
  5404                              <1> ;									       :
  5405                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5406                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5407                              <1> ;									       :
  5408                              <1> ;-------------------------------------------------------------------------------
  5409                              <1> 
  5410                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5411                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5412                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5413                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5414                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5415                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5416                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5417                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5418                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5419                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5420                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5421                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5422                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5423                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5424                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5425                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5426                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5427                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5428                              <1> 
  5429                              <1> ;--------------------------------------------------------
  5430                              <1> ;							:
  5431                              <1> ; FIXED DISK PARAMETER TABLE				:
  5432                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5433                              <1> ;							:
  5434                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5435                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5436                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5437                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5438                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5439                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5440                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5441                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5442                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5443                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5444                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5445                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5446                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5447                              <1> ;							:
  5448                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5449                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5450                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5451                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5452                              <1> ;							:
  5453                              <1> ;--------------------------------------------------------
  5454                              <1> 
  5455                              <1> ;--------------------------------------------------------
  5456                              <1> ;							:
  5457                              <1> ; HARDWARE SPECIFIC VALUES				:
  5458                              <1> ;							:
  5459                              <1> ;  -  CONTROLLER I/O PORT				:
  5460                              <1> ;							:
  5461                              <1> ;     > WHEN READ FROM: 				:
  5462                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5463                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5464                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5465                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5466                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5467                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5468                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5469                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5470                              <1> ;							:
  5471                              <1> ;     > WHEN WRITTEN TO:				:
  5472                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5473                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5474                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5475                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5476                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5477                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5478                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5479                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5480                              <1> ;							:
  5481                              <1> ;--------------------------------------------------------
  5482                              <1> 
  5483                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5484                              <1> ;HF1_PORT	equ	0170h	
  5485                              <1> ;HF_REG_PORT	EQU	03F6H
  5486                              <1> ;HF1_REG_PORT	equ	0376h
  5487                              <1> 
  5488                              <1> HDC1_BASEPORT	equ	1F0h
  5489                              <1> HDC2_BASEPORT	equ	170h		
  5490                              <1> 
  5491                              <1> align 2
  5492                              <1> 
  5493                              <1> ;-----		STATUS REGISTER
  5494                              <1> 
  5495                              <1> ST_ERROR	EQU	00000001B	;
  5496                              <1> ST_INDEX	EQU	00000010B	;
  5497                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5498                              <1> ST_DRQ		EQU	00001000B	;
  5499                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5500                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5501                              <1> ST_READY	EQU	01000000B	;
  5502                              <1> ST_BUSY 	EQU	10000000B	;
  5503                              <1> 
  5504                              <1> ;-----		ERROR REGISTER
  5505                              <1> 
  5506                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5507                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5508                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5509                              <1> ;		EQU	00001000B	; NOT USED
  5510                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5511                              <1> ;		EQU	00100000B	; NOT USED
  5512                              <1> ERR_DATA_ECC	EQU	01000000B
  5513                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5514                              <1> 
  5515                              <1> 
  5516                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5517                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5518                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5519                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5520                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5521                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5522                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5523                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5524                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5525                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5526                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5527                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5528                              <1> 
  5529                              <1> ;MAX_FILE	EQU	2
  5530                              <1> ;S_MAX_FILE	EQU	2
  5531                              <1> MAX_FILE	equ	4		; 22/12/2014
  5532                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5533                              <1> 
  5534                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5535                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5536                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5537                              <1> 
  5538                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5539                              <1> 
  5540                              <1> ;-----		COMMAND BLOCK REFERENCE
  5541                              <1> 
  5542                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5543                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5544                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5545                              <1> ; 19/12/2014
  5546                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5547                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5548                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5549                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5550                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5551                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5552                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5553                              <1> 
  5554                              <1> align 2
  5555                              <1> 
  5556                              <1> ;----------------------------------------------------------------
  5557                              <1> ; FIXED DISK I/O SETUP						:
  5558                              <1> ;								:
  5559                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5560                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5561                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5562                              <1> ;								:
  5563                              <1> ;----------------------------------------------------------------
  5564                              <1> 
  5565                              <1> DISK_SETUP:
  5566                              <1> 	;CLI
  5567                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5568                              <1> 	;xor	ax,ax
  5569                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5570                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5571                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5572                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5573                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5574                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5575                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5576                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5577                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5578                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5579                              <1> 	;;MOV	[HDISK_INT+2],CS
  5580                              <1> 	;mov	[HDISK_INT1+2],CS
  5581                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5582                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5583                              <1> 	;mov	[HDISK_INT2+2],CS
  5584                              <1> 	;
  5585                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5586                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5587                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5588                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5589                              <1> 	;push	cs
  5590                              <1> 	;pop	ds
  5591                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5592                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5593 000025A2 C705[34710000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5593 000025AA 0900                <1>
  5594                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5595                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5596 000025AC C705[38710000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5596 000025B4 0900                <1>
  5597                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5598                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5599 000025B6 C705[3C710000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5599 000025BE 0900                <1>
  5600                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5601                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5602 000025C0 C705[40710000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5602 000025C8 0900                <1>
  5603                              <1> 	;
  5604                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5605                              <1> 	;;;AND	AL,0BFH
  5606                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5607                              <1> 	;;;JMP	$+2
  5608                              <1> 	;;IODELAY
  5609                              <1> 	;;OUT	INTB01,AL
  5610                              <1> 	;;IODELAY
  5611                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5612                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5613                              <1> 	;;;JMP	$+2
  5614                              <1> 	;;IODELAY
  5615                              <1> 	;;OUT	INTA01,AL
  5616                              <1> 	;
  5617                              <1> 	;STI
  5618                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5619                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5620                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5621                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5622                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5623                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5624                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5625                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5626                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5627                              <1> 	;mov	si, hd0_type
  5628 000025CA BE[906B0000]        <1> 	mov	esi, hd0_type
  5629                              <1> 	;mov	cx, 4
  5630 000025CF B904000000          <1> 	mov	ecx, 4
  5631                              <1> hde_l:
  5632 000025D4 AC                  <1> 	lodsb
  5633 000025D5 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5634 000025D7 7206                <1> 	jb	short _L4
  5635 000025D9 FE05[30710000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5636                              <1> _L4: ; 26/02/2015
  5637 000025DF E2F3                <1> 	loop	hde_l	
  5638                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5639                              <1> ;L4:
  5640                              <1> 	; 
  5641                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5642                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5643                              <1> 	;;mov 	cl, 3
  5644                              <1> 	;;
  5645                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5646                              <1> ;;hdc_dl:
  5647                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5648                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5649                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5650                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5651                              <1> 	;;jnc	short hdc_reset0
  5652                              <1> 	;;loop	hdc_dl
  5653                              <1> 	;;; 27/12/2014
  5654                              <1> 	;;stc
  5655                              <1> 	;;retn
  5656                              <1> 	;
  5657                              <1> ;;hdc_reset0:
  5658                              <1> 	; 18/01/2015
  5659 000025E1 8A0D[30710000]      <1> 	mov	cl, [HF_NUM]
  5660 000025E7 20C9                <1> 	and	cl, cl
  5661 000025E9 740D                <1> 	jz	short POD_DONE
  5662                              <1> 	;
  5663 000025EB B27F                <1> 	mov	dl, 7Fh
  5664                              <1> hdc_reset1:
  5665 000025ED FEC2                <1> 	inc	dl
  5666                              <1> 	;; 31/12/2015
  5667                              <1> 	;;push	dx
  5668                              <1> 	;;push	cx
  5669                              <1> 	;;push	ds
  5670                              <1> 	;;sub	ax, ax
  5671                              <1> 	;;mov	ds, ax
  5672                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5673                              <1> 	;;pop	ds
  5674                              <1> 	;;MOV	BX,AX
  5675                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5676                              <1> 	;;MOV	CX,AX
  5677                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5678                              <1> 	;;
  5679                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5680                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5681                              <1> 	;;pop	cx
  5682                              <1> 	;;pop	dx
  5683                              <1> 	;;
  5684                              <1> 	; 18/01/2015
  5685 000025EF B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5686                              <1> 	;int	13h
  5687 000025F1 E8A4FFFFFF          <1> 	call	int13h
  5688 000025F6 E2F5                <1> 	loop	hdc_reset1
  5689                              <1> POD_DONE:
  5690 000025F8 C3                  <1> 	RETn
  5691                              <1> 
  5692                              <1> ;;-----	POD_ERROR
  5693                              <1> 
  5694                              <1> ;;CTL_ERRX:
  5695                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5696                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5697                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5698                              <1> ;	;JMP	short POD_DONE
  5699                              <1> 
  5700                              <1> ;;HD_RESET_1:
  5701                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5702                              <1> ;;	;PUSH	CX
  5703                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5704                              <1> ;;	INT	13H
  5705                              <1> ;;	JC	short RES_2
  5706                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5707                              <1> ;;	INT	13H
  5708                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5709                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5710                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5711                              <1> ;;					; (30 seconds)		
  5712                              <1> ;;	;cmc
  5713                              <1> ;;	;JNC	short RES_1
  5714                              <1> ;;	jb	short RES_1
  5715                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5716                              <1> ;;	;TEST	DL,1
  5717                              <1> ;;	;JNZ	RES_E1
  5718                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5719                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5720                              <1> ;;	;JMP	SHORT RES_E1
  5721                              <1> ;;RES_ER: ; 22/12/2014
  5722                              <1> ;;RES_OK:
  5723                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5724                              <1> ;;	;POP	BX
  5725                              <1> ;;	RETn
  5726                              <1> ;;
  5727                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5728                              <1> ;;	INT	13H
  5729                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5730                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5731                              <1> ;;	INT	13H
  5732                              <1> ;;	JC	short RES_ER
  5733                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5734                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5735                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5736                              <1> ;;	INT	13H
  5737                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5738                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5739                              <1> ;;	JE	short RES_OK
  5740                              <1> ;;	CMP	AH,DATA_CORRECTED
  5741                              <1> ;;	JE	short RES_OK
  5742                              <1> ;;	CMP	AH,BAD_ECC
  5743                              <1> ;;	JE	short RES_OK
  5744                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5745                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5746                              <1> ;;					; (60 seconds)		
  5747                              <1> ;;	cmc
  5748                              <1> ;;	JC	short RES_ER		; FAILED
  5749                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5750                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5751                              <1> ;;	AND	AL,3FH
  5752                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5753                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5754                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5755                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5756                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5757                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5758                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5759                              <1> ;;	;TEST	DL,1
  5760                              <1> ;;	;JNZ	short RES_E1
  5761                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5762                              <1> ;;;RES_E1:
  5763                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5764                              <1> ;;;RES_OK:
  5765                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5766                              <1> ;;	;POP	BX
  5767                              <1> ;;	;RETn
  5768                              <1> ;
  5769                              <1> ;;SET_FAIL:
  5770                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5771                              <1> ;	;CALL	CMOS_READ
  5772                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5773                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5774                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5775                              <1> ;	;RETn
  5776                              <1> ;
  5777                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5778                              <1> ;	;POP	AX			; SAVE RETURN
  5779                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5780                              <1> ;	;POP	BX
  5781                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5782                              <1> ;	;PUSH	CX
  5783                              <1> ;	;PUSH	AX
  5784                              <1> ;	;push	ds
  5785                              <1> ;	;xor	ax, ax
  5786                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5787                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5788                              <1> ;	;				; BX = START TIME
  5789                              <1> ;	;				; CX = END TIME
  5790                              <1> ;	;pop	ds
  5791                              <1> ;	;CMP	BX,CX
  5792                              <1> ;	;JB	short TCHK1		; START < END
  5793                              <1> ;	;CMP	BX,AX
  5794                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5795                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5796                              <1> ;;TCHK1: CMP	AX,BX
  5797                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5798                              <1> ;;TCHK2: CMP	AX,CX
  5799                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5800                              <1> ;;					; OR CURRENT < END < START
  5801                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5802                              <1> ;;	RETn
  5803                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5804                              <1> ;;	RETn
  5805                              <1> ;;
  5806                              <1> ;;int_13h:
  5807                              <1> 
  5808                              <1> ;----------------------------------------
  5809                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5810                              <1> ;----------------------------------------
  5811                              <1> 
  5812                              <1> DISK_IO:
  5813 000025F9 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5814                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5815                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5816                              <1> 	;;call	int40h
  5817                              <1> 	;jb	DISKETTE_IO_1
  5818                              <1> 	; 05/12/2021
  5819 000025FC 7305                <1> 	jnb	short A1
  5820 000025FE E960F1FFFF          <1> 	jmp	DISKETTE_IO_1
  5821                              <1> ;RET_2:
  5822                              <1> 	;RETf	2			; BACK TO CALLER
  5823                              <1> ;	retf	4
  5824                              <1> A1:
  5825 00002603 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5826                              <1> 	;; 04/01/2015
  5827                              <1> 	;;OR	AH,AH
  5828                              <1> 	;;JNZ	short A2
  5829                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5830                              <1> 	;;SUB	AH,AH
  5831 00002604 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5832 00002607 772E                <1> 	JA	short RET_2
  5833                              <1> 	; 18/01/2015
  5834 00002609 08E4                <1> 	or	ah,ah
  5835 0000260B 742D                <1> 	jz	short A4
  5836 0000260D 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5837 00002610 7504                <1> 	jne	short A2
  5838 00002612 28E4                <1> 	sub	ah,ah	; Reset
  5839 00002614 EB24                <1> 	jmp	short A4
  5840                              <1> A2:
  5841 00002616 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5842                              <1> 	;JNZ	short A3
  5843                              <1>         ;JMP    GET_PARM_N
  5844                              <1> 	;je	GET_PARM_N
  5845                              <1> 	; 05/12/2021
  5846 00002619 7505                <1> 	jne	short A3
  5847 0000261B E90D030000          <1> 	jmp	GET_PARM_N
  5848                              <1> A3:	
  5849 00002620 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5850                              <1> 	;JNZ	short A4
  5851                              <1>         ;JMP    READ_DASD_TYPE
  5852                              <1> 	;je	READ_DASD_TYPE
  5853                              <1> 	; 05/12/2021
  5854 00002623 7505                <1> 	jne	short A3_A4
  5855 00002625 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5856                              <1> A3_A4:
  5857                              <1> 	; 02/02/2015
  5858 0000262A 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5859                              <1> 	; 12/01/2015
  5860 0000262D F5                  <1> 	cmc
  5861 0000262E 730A                <1> 	jnc	short A4
  5862                              <1> 	; 30/01/2015
  5863                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5864 00002630 C605[2F710000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5865                              <1> 	;jmp	short RET_2
  5866                              <1> RET_2:
  5867 00002637 CA0400              <1> 	retf	4
  5868                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5869 0000263A C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5870 0000263E 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5871 0000263F 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5872 00002640 52                  <1> 	PUSH	eDX
  5873 00002641 1E                  <1> 	PUSH	DS
  5874 00002642 06                  <1> 	PUSH	ES
  5875 00002643 56                  <1> 	PUSH	eSI
  5876 00002644 57                  <1> 	PUSH	eDI
  5877                              <1> 	;;04/01/2015
  5878                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5879                              <1> 	;;JNZ	short A5
  5880                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5881                              <1> ;;A5:	
  5882                              <1> 	;push	cs
  5883                              <1> 	;pop	ds
  5884                              <1> 	; 21/02/2015
  5885                              <1> 	;push	ax
  5886                              <1> 	; 05/12/2021
  5887 00002645 50                  <1> 	push	eax
  5888 00002646 66B81000            <1> 	mov	ax, KDATA
  5889 0000264A 8ED8                <1> 	mov	ds, ax
  5890 0000264C 8EC0                <1> 	mov	es, ax	
  5891                              <1> 	;pop	ax
  5892                              <1> 	; 05/12/2021
  5893 0000264E 58                  <1> 	pop	eax
  5894 0000264F E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5895                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5896 00002654 8A25[2F710000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5897 0000265A 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5898 0000265D F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5899 0000265E 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5900 0000265F 5E                  <1> 	POP	eSI
  5901 00002660 07                  <1>         POP     ES
  5902 00002661 1F                  <1>         POP     DS
  5903 00002662 5A                  <1> 	POP	eDX
  5904 00002663 59                  <1> 	POP	eCX
  5905 00002664 5B                  <1> 	POP	eBX
  5906 00002665 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5907                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5908 00002666 CA0400              <1> 	retf	4
  5909                              <1> ; 21/02/2015
  5910                              <1> ;       dw --> dd
  5911                              <1> M1:					; FUNCTION TRANSFER TABLE
  5912 00002669 [22280000]          <1> 	dd	DISK_RESET		; 000H
  5913 0000266D [97280000]          <1> 	dd	RETURN_STATUS		; 001H
  5914 00002671 [A4280000]          <1> 	dd	DISK_READ		; 002H
  5915 00002675 [AD280000]          <1> 	dd	DISK_WRITE		; 003H
  5916 00002679 [B6280000]          <1> 	dd	DISK_VERF		; 004H
  5917 0000267D [CE280000]          <1> 	dd	FMT_TRK 		; 005H
  5918 00002681 [18280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5919 00002685 [18280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5920 00002689 [18280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5921 0000268D [8F290000]          <1> 	dd	INIT_DRV		; 009H
  5922 00002691 [EE290000]          <1> 	dd	RD_LONG 		; 00AH
  5923 00002695 [F7290000]          <1> 	dd	WR_LONG 		; 00BH
  5924 00002699 [002A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5925 0000269D [22280000]          <1> 	dd	DISK_RESET		; 00DH
  5926 000026A1 [18280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5927 000026A5 [18280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5928 000026A9 [282A0000]          <1> 	dd	TST_RDY 		; 010H
  5929 000026AD [4C2A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5930 000026B1 [18280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5931 000026B5 [18280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5932 000026B9 [822A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5933                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5934 000026BD [18280000]          <1> 	dd	BAD_COMMAND		; 015h
  5935 000026C1 [18280000]          <1> 	dd	BAD_COMMAND		; 016h
  5936 000026C5 [18280000]          <1> 	dd	BAD_COMMAND		; 017h
  5937 000026C9 [18280000]          <1> 	dd	BAD_COMMAND		; 018h
  5938 000026CD [18280000]          <1> 	dd	BAD_COMMAND		; 019h
  5939 000026D1 [18280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5940 000026D5 [A4280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5941 000026D9 [AD280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5942                              <1> M1L     EQU    $-M1
  5943                              <1> 
  5944                              <1> DISK_IO_CONT:
  5945                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5946 000026DD 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5947                              <1> 	;;JNZ	short SU0
  5948                              <1>         ;;JMP	RETURN_STATUS
  5949                              <1> 	;je	RETURN_STATUS
  5950                              <1> 	; 05/12/2021
  5951 000026E0 7505                <1> 	jne	short SU0
  5952 000026E2 E9B0010000          <1> 	jmp	RETURN_STATUS
  5953                              <1> SU0:
  5954 000026E7 C605[2F710000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5955                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5956                              <1> 	;mov	si, bx ;; 14/02/2015
  5957 000026EE 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5958 000026F0 8A1D[30710000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5959                              <1> 	;; 04/01/2015
  5960                              <1> 	;;PUSH	AX
  5961 000026F6 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5962                              <1> 					; (get drive number as 0 to 3)
  5963 000026F9 38D3                <1> 	CMP	BL,DL
  5964                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5965                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5966                              <1> 	; 05/12/2021
  5967 000026FB 7705                <1> 	ja	short su0_su1
  5968 000026FD E916010000          <1> 	jmp	BAD_COMMAND
  5969                              <1> su0_su1:
  5970                              <1>         ;;03/01/2015
  5971 00002702 29DB                <1> 	sub	ebx, ebx
  5972 00002704 88D3                <1> 	mov	bl, dl
  5973                              <1> 	;sub	bh, bh
  5974 00002706 883D[44710000]      <1> 	mov	[LBAMode], bh 	; 0
  5975                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5976                              <1> 	;test	byte [ebx+hd0_type], 1
  5977                              <1> 	;jz	short su1		; no
  5978                              <1> 	;inc	byte [LBAMode]
  5979                              <1> ;su1:
  5980                              <1> 	; 21/02/2015 (32 bit modification)
  5981                              <1> 	; 04/01/2015
  5982                              <1> 	;push	ax ; ***
  5983                              <1> 	; 05/12/2021
  5984 0000270C 50                  <1> 	push	eax ; ***
  5985                              <1> 	;PUSH	ES ; **
  5986                              <1> 	;PUSH	DX ; *
  5987                              <1> 	; 05/12/2021
  5988 0000270D 52                  <1> 	push	edx ; *
  5989                              <1> 	;push	ax
  5990 0000270E 50                  <1> 	push	eax
  5991 0000270F E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5992                              <1> 	; 02/02/2015
  5993                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5994 00002714 668B4310            <1> 	mov	ax, [ebx+16]
  5995 00002718 66A3[846B0000]      <1> 	mov	[HF_PORT], ax
  5996                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5997 0000271E 668B5312            <1> 	mov	dx, [ebx+18]
  5998 00002722 668915[866B0000]    <1> 	mov	[HF_REG_PORT], dx
  5999                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  6000 00002729 8A4314              <1> 	mov	al, [ebx+20]
  6001                              <1> 	; 23/02/2015
  6002 0000272C A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  6003 0000272E 7406                <1> 	jz 	short su1
  6004 00002730 FE05[44710000]      <1> 	inc	byte [LBAMode] ; 1 
  6005                              <1> su1: 	 
  6006 00002736 C0E804              <1> 	shr 	al, 4
  6007 00002739 2401                <1> 	and	al, 1			
  6008 0000273B A2[886B0000]        <1> 	mov	[hf_m_s], al 
  6009                              <1> 	;
  6010                              <1> 	; 03/01/2015
  6011                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  6012 00002740 8A4308              <1> 	mov	al, [ebx+8]
  6013                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  6014 00002743 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  6015                              <1> 					; Control Byte:  (= 08h, here)
  6016                              <1> 					; bit 0 - 0
  6017                              <1> 					; bit 1 - nIEN (1 = disable irq)
  6018                              <1> 					; bit 2 - SRST (software RESET)
  6019                              <1> 					; bit 3 - use extra heads (8 to 15)
  6020                              <1> 					;         -always set to 1-	
  6021                              <1> 					; (bits 3 to 7 are reserved
  6022                              <1> 					;          for ATA devices)
  6023 00002744 8A25[31710000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6024 0000274A 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  6025 0000274D 08C4                <1> 	OR	AH,AL
  6026 0000274F 8825[31710000]      <1> 	MOV	[CONTROL_BYTE],AH	
  6027                              <1> 	; 04/01/2015
  6028                              <1> 	;pop	ax
  6029                              <1> 	; 05/12/2021
  6030 00002755 58                  <1> 	pop	eax
  6031                              <1> 	;pop	dx ; * ;; 14/02/2015
  6032                              <1> 	; 05/12/2021
  6033 00002756 5A                  <1> 	pop	edx ; *
  6034 00002757 20E4                <1> 	and	ah, ah	; Reset function ?
  6035 00002759 7506                <1> 	jnz	short su2
  6036                              <1> 	;;pop	dx ; * ;; 14/02/2015
  6037                              <1> 	;pop	es ; **
  6038                              <1> 	;pop	ax ; ***
  6039                              <1> 	; 05/12/2021
  6040 0000275B 58                  <1> 	pop	eax ; ***	
  6041                              <1> 	;;pop	bx
  6042 0000275C E9C1000000          <1>         jmp     DISK_RESET
  6043                              <1> su2:
  6044 00002761 803D[44710000]00    <1> 	cmp	byte [LBAMode], 0
  6045 00002768 765E                <1> 	jna	short su3
  6046                              <1> 	;
  6047                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6048 0000276A 80FC1B              <1> 	cmp	ah, 1Bh
  6049 0000276D 720B                <1> 	jb	short lbarw1
  6050 0000276F 80FC1C              <1> 	cmp	ah, 1Ch
  6051 00002772 7759                <1> 	ja 	short invldfnc
  6052                              <1> 	;;pop	dx ; * ; 14/02/2015
  6053                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6054 00002774 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6055                              <1> 	;; 14/02/2015
  6056 00002776 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6057                              <1> 	;;mov	dx, bx
  6058                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6059                              <1> 	;;mov	bx, di
  6060                              <1> 	;mov	si, di ; Buffer offset
  6061 00002778 EB2E                <1> 	jmp	short lbarw2
  6062                              <1> lbarw1:
  6063                              <1> 	; convert CHS to LBA
  6064                              <1> 	;
  6065                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6066                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6067                              <1> 	;	+ Sector - 1
  6068                              <1> 	;push	dx ; * ;; 14/02/2015
  6069                              <1> 	; 05/12/2021
  6070 0000277A 52                  <1> 	push	edx ; *
  6071                              <1> 	;xor	dh, dh
  6072 0000277B 31D2                <1> 	xor	edx, edx
  6073                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6074 0000277D 8A530E              <1> 	mov	dl, [ebx+14]
  6075                              <1> 	;xor	ah, ah
  6076 00002780 31C0                <1> 	xor	eax, eax
  6077                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6078 00002782 8A4302              <1> 	mov	al, [ebx+2]
  6079 00002785 FEC8                <1> 	dec	al
  6080                              <1> 	;inc	ax		; 0 =  256
  6081 00002787 40                  <1> 	inc	eax ; 05/12/2021
  6082 00002788 66F7E2              <1> 	mul 	dx
  6083                              <1> 		; AX = # of Heads" * Sectors/Track
  6084 0000278B 6689CA              <1> 	mov	dx, cx
  6085                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6086 0000278E 83E13F              <1> 	and	ecx, 3fh
  6087 00002791 86D6                <1> 	xchg	dl, dh
  6088 00002793 C0EE06              <1> 	shr	dh, 6
  6089                              <1> 		; DX = cylinder (0 to 1023)
  6090                              <1> 	;mul 	dx
  6091                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6092 00002796 F7E2                <1> 	mul	edx
  6093 00002798 FEC9                <1> 	dec	cl  ; sector - 1
  6094                              <1> 	;add	ax, cx
  6095                              <1> 	;adc	dx, 0
  6096                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6097 0000279A 01C8                <1> 	add	eax, ecx
  6098                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6099                              <1> 	; 05/12/2021
  6100 0000279C 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6101                              <1> 	;push	dx
  6102                              <1> 	;push	ax
  6103 0000279D 50                  <1> 	push	eax
  6104                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6105 0000279E 8A430E              <1> 	mov	al, [ebx+14]
  6106 000027A1 F6E5                <1> 	mul	ch
  6107                              <1> 		; AX = Head * Sectors/Track
  6108 000027A3 6699                <1>         cwd
  6109                              <1> 	;pop	dx
  6110 000027A5 5A                  <1> 	pop	edx
  6111                              <1> 	;add	ax, dx
  6112                              <1> 	;pop	dx
  6113                              <1> 	;adc	dx, 0 ; add carry bit
  6114 000027A6 01D0                <1> 	add	eax, edx
  6115                              <1> lbarw2:
  6116 000027A8 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6117 000027AA 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6118 000027AC C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6119                              <1> 				; NOTE: Features register (1F1h, 171h)
  6120                              <1> 				; is not used for ATA device R/W functions. 
  6121                              <1> 				; It is old/obsolete 'write precompensation'
  6122                              <1> 				; register and error register
  6123                              <1> 				; for old ATA/IDE devices.
  6124                              <1> 	; 18/01/2014
  6125                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6126 000027B0 8A0D[886B0000]      <1> 	mov	cl, [hf_m_s]
  6127                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6128                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6129                              <1> 				; bit 6 = 1 = LBA mode
  6130                              <1> 				; bit 7 = 1
  6131 000027B6 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6132                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6133 000027B9 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6134 000027BE C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6135                              <1> 	;or	dh, ch
  6136 000027C1 09C8                <1> 	or	eax, ecx	
  6137                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6138                              <1> 				  ; (Sector Number Register)
  6139                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6140                              <1> 				  ; (Cylinder Low Register)
  6141                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6142                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6143                              <1> 				  ; (Cylinder High Register)
  6144                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6145                              <1> 				  ; (Drive/Head Register)
  6146                              <1> 	
  6147                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6148 000027C3 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6149                              <1> 	;14/02/2015
  6150                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6151 000027C6 EB37                <1> 	jmp	short su4
  6152                              <1> su3:
  6153                              <1> 	; 02/02/2015 
  6154                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6155 000027C8 80FC14              <1> 	cmp 	ah, 14h
  6156 000027CB 7603                <1> 	jna 	short chsfnc
  6157                              <1> invldfnc:
  6158                              <1>         ; 14/02/2015  
  6159                              <1> 	;pop	es ; **
  6160                              <1>         ;pop	ax ; ***
  6161                              <1>         ; 05/12/2021
  6162 000027CD 58                  <1> 	pop	eax ; ***
  6163                              <1> 	;jmp	short BAD_COMMAND_POP
  6164 000027CE EB48                <1>         jmp     short BAD_COMMAND
  6165                              <1> chsfnc:	
  6166                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6167 000027D0 668B4305            <1> 	mov	ax, [ebx+5]
  6168 000027D4 66C1E802            <1> 	SHR	AX,2
  6169 000027D8 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6170                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6171                              <1> 	;;PUSH	DX
  6172                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6173                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6174                              <1> 	;;POP	DX ; * 
  6175                              <1> 	;;POP	ES ; **
  6176                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6177                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6178                              <1> 	;;OR	AH,AL
  6179                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6180                              <1> 	;
  6181 000027DB 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6182 000027DD 243F                <1> 	AND	AL,3FH
  6183 000027DF 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6184 000027E2 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6185 000027E5 88C8                <1> 	MOV	AL,CL
  6186 000027E7 C0E806              <1> 	SHR	AL,6
  6187 000027EA 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6188                              <1> 	;;05/01/2015
  6189                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6190 000027ED A0[886B0000]        <1> 	mov	al, [hf_m_s]
  6191 000027F2 C0E004              <1> 	SHL	AL,4
  6192 000027F5 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6193 000027F8 08F0                <1> 	OR	AL,DH
  6194                              <1> 	;OR	AL,80H or 20H
  6195 000027FA 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6196 000027FC 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6197                              <1> su4:
  6198                              <1> 	;POP	ES ; **
  6199                              <1>         ;; 14/02/2015
  6200                              <1>         ;;POP   AX
  6201                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6202                              <1>         ;;PUSH  AX
  6203                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6204                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6205                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6206                              <1> 	;pop	ax ; ***
  6207                              <1> 	; 05/12/2021
  6208 000027FF 58                  <1> 	pop	eax ; ***
  6209 00002800 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6210 00002803 29DB                <1>         sub	ebx, ebx
  6211 00002805 88E3                <1> 	mov     bl, ah
  6212                              <1>         ;xor	bh, bh
  6213                              <1>         ;sal	bx, 1
  6214 00002807 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6215                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6216                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6217                              <1>         ;;JNB   short BAD_COMMAND_POP
  6218                              <1>         ;cmp	bx, M1L
  6219 0000280B 83FB74              <1> 	cmp	ebx, M1L
  6220 0000280E 7308                <1> 	jnb	short BAD_COMMAND
  6221                              <1>         ;xchg	bx, si
  6222 00002810 87DE                <1>         xchg	ebx, esi
  6223                              <1> 	;;;POP	AX			; RESTORE AX
  6224                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6225                              <1> 	
  6226                              <1> 	;;PUSH	CX
  6227                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6228                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6229                              <1> 	;SHR	CX,4
  6230                              <1> 	;MOV	AX,ES
  6231                              <1> 	;ADD	AX,CX
  6232                              <1> 	;MOV	ES,AX
  6233                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6234                              <1> 	;;POP	AX
  6235                              <1> 	;;POP	CX
  6236                              <1> 	;;JMP	word [CS:SI+M1]
  6237                              <1> 	;jmp	word [SI+M1]
  6238 00002812 FFA6[69260000]      <1> 	jmp	dword [esi+M1]
  6239                              <1> ;;BAD_COMMAND_POP:
  6240                              <1> ;;	POP	AX
  6241                              <1> ;;	POP	BX
  6242                              <1> BAD_COMMAND:
  6243 00002818 C605[2F710000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6244 0000281F B000                <1> 	MOV	AL,0
  6245 00002821 C3                  <1> 	RETn
  6246                              <1> 
  6247                              <1> ;----------------------------------------
  6248                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6249                              <1> ;----------------------------------------
  6250                              <1> 
  6251                              <1> ; 18-1-2015 : one controller reset (not other one)
  6252                              <1> 
  6253                              <1> DISK_RESET:
  6254 00002822 FA                  <1> 	CLI
  6255 00002823 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6256                              <1> 	;JMP	$+2
  6257                              <1> 	IODELAY
  2144 00002825 EB00                <2>  jmp short $+2
  2145 00002827 EB00                <2>  jmp short $+2
  6258                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6259 00002829 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6260 0000282B E6A1                <1> 	OUT	INTB01,AL
  6261 0000282D FB                  <1> 	STI				; START INTERRUPTS
  6262                              <1> 	; 14/02/2015
  6263                              <1> 	;mov	di, dx
  6264                              <1> 	; 05/12/2021
  6265 0000282E 89D7                <1> 	mov	edi, edx	
  6266                              <1> 	; 04/01/2015
  6267                              <1> 	;xor	di,di
  6268                              <1> drst0:
  6269 00002830 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6270                              <1> 	;MOV	DX,HF_REG_PORT
  6271 00002832 668B15[866B0000]    <1> 	MOV	DX,[HF_REG_PORT]
  6272 00002839 EE                  <1> 	OUT	DX,AL			; RESET
  6273                              <1> ;	MOV	CX,10			; DELAY COUNT
  6274                              <1> ;DRD:	DEC	CX
  6275                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6276                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6277 0000283A B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6278 0000283F E877ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6279                              <1>                                         ; 40 micro seconds)
  6280 00002844 A0[31710000]        <1> 	mov	al,[CONTROL_BYTE]
  6281 00002849 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6282 0000284B EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6283 0000284C E807040000          <1> 	CALL	NOT_BUSY
  6284 00002851 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6285 00002853 668B15[846B0000]    <1> 	MOV	DX,[HF_PORT]
  6286 0000285A FEC2                <1> 	inc	dl  ; HF_PORT+1
  6287                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6288                              <1>         ;mov	cl, 10
  6289 0000285C B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6290                              <1> drst1:
  6291 00002861 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6292 00002862 3C01                <1> 	CMP	AL,1
  6293                              <1> 	; 04/01/2015
  6294 00002864 740A                <1> 	jz	short drst2
  6295                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6296                              <1>         	; Drive/Head Register - bit 4
  6297 00002866 E2F9                <1> 	loop	drst1
  6298                              <1> DRERR:	
  6299 00002868 C605[2F710000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6300 0000286F C3                  <1> 	RETn
  6301                              <1> drst2:
  6302                              <1> 	; 14/02/2015
  6303                              <1> 	;mov	dx, di
  6304                              <1> 	; 05/12/2021
  6305 00002870 89FA                <1> 	mov	edx, edi
  6306                              <1> ;drst3:
  6307                              <1> ;	; 05/01/2015
  6308                              <1> ;	shl 	di,1
  6309                              <1> ;	; 04/01/2015
  6310                              <1> ;	mov	ax,[di+hd_cports]
  6311                              <1> ;	cmp	ax,[HF_REG_PORT]
  6312                              <1> ;	je	short drst4
  6313                              <1> ;	mov	[HF_REG_PORT], ax
  6314                              <1> ;	; 03/01/2015
  6315                              <1> ;	mov	ax,[di+hd_ports]
  6316                              <1> ;       mov     [HF_PORT], ax
  6317                              <1> ;	; 05/01/2014
  6318                              <1> ;	shr	di,1
  6319                              <1> ;	; 04/01/2015
  6320                              <1> ;	jmp	short drst0	; reset other controller
  6321                              <1> ;drst4:
  6322                              <1> ;	; 05/01/2015
  6323                              <1> ;	shr	di,1
  6324                              <1> ;	mov	al,[di+hd_dregs]
  6325                              <1> ;	and	al,10h ; bit 4 only
  6326                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6327                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6328                              <1> 	;
  6329 00002872 A0[886B0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6330 00002877 A801                <1> 	test	al,1
  6331                              <1> ;	jnz	short drst6
  6332 00002879 7516                <1>         jnz     short drst4
  6333 0000287B 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6334                              <1> ;drst5:
  6335                              <1> drst3:
  6336 0000287F E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6337                              <1> 	;mov	dx,di
  6338 00002884 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6339                              <1> 	; 04/01/2014
  6340                              <1> ;	inc	di
  6341                              <1> ;	mov	dx,di
  6342                              <1> ;	cmp	dl,[HF_NUM]
  6343                              <1> ;	jb	short drst3
  6344                              <1> ;DRE:
  6345 00002889 C605[2F710000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6346 00002890 C3                  <1> 	RETn
  6347                              <1> ;drst6:
  6348                              <1> drst4:		; Drive/Head Register - bit 4
  6349 00002891 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6350                              <1>         ;jmp    short drst5
  6351 00002895 EBE8                <1>         jmp     short drst3
  6352                              <1> 
  6353                              <1> ;----------------------------------------
  6354                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6355                              <1> ;----------------------------------------
  6356                              <1> 
  6357                              <1> RETURN_STATUS:
  6358 00002897 A0[2F710000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6359 0000289C C605[2F710000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6360 000028A3 C3                  <1> 	RETn
  6361                              <1> 
  6362                              <1> ;----------------------------------------
  6363                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6364                              <1> ;----------------------------------------
  6365                              <1> 
  6366                              <1> DISK_READ:
  6367 000028A4 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6368 000028A8 E92A020000          <1>         JMP     COMMANDI
  6369                              <1> 
  6370                              <1> ;----------------------------------------
  6371                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6372                              <1> ;----------------------------------------
  6373                              <1> 
  6374                              <1> DISK_WRITE:
  6375 000028AD C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6376 000028B1 E976020000          <1>         JMP     COMMANDO
  6377                              <1> 
  6378                              <1> ;----------------------------------------
  6379                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6380                              <1> ;----------------------------------------
  6381                              <1> 
  6382                              <1> DISK_VERF:
  6383 000028B6 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6384 000028BA E8E4020000          <1> 	CALL	COMMAND
  6385 000028BF 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6386 000028C1 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6387 000028C6 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6388 000028C8 E8E3030000          <1> 	CALL	CHECK_STATUS
  6389                              <1> VERF_EXIT:
  6390 000028CD C3                  <1> 	RETn
  6391                              <1> 
  6392                              <1> ;----------------------------------------
  6393                              <1> ;	FORMATTING	     (AH = 05H) :
  6394                              <1> ;----------------------------------------
  6395                              <1> 
  6396                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6397 000028CE C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6398                              <1> 	;PUSH	ES
  6399                              <1> 	;PUSH	BX
  6400 000028D2 53                  <1> 	push	ebx
  6401 000028D3 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6402                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6403 000028D8 8A430E              <1> 	mov	al, [ebx+14]
  6404 000028DB 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6405 000028DE 5B                  <1> 	pop	ebx
  6406                              <1> 	;POP	BX
  6407                              <1> 	;POP	ES
  6408 000028DF E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6409                              <1> 
  6410                              <1> ;----------------------------------------
  6411                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6412                              <1> ;----------------------------------------
  6413                              <1> 
  6414                              <1> READ_DASD_TYPE:
  6415                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6416 000028E4 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6417                              <1> 	;PUSH	ES
  6418 000028E5 53                  <1> 	PUSH	eBX
  6419                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6420                              <1> 	;push	cs
  6421                              <1> 	;pop	ds
  6422 000028E6 66BB1000            <1>         mov	bx, KDATA
  6423 000028EA 8EDB                <1> 	mov	ds, bx
  6424                              <1> 	;mov	es, bx
  6425 000028EC C605[2F710000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6426 000028F3 8A1D[30710000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6427 000028F9 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6428 000028FC 38D3                <1> 	CMP	BL,DL
  6429 000028FE 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6430 00002900 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6431                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6432 00002905 8A4302              <1> 	mov	al, [ebx+2]
  6433                              <1> 	;MOV	CL,[ES:BX+14]
  6434 00002908 8A4B0E              <1> 	mov	cl, [ebx+14]
  6435 0000290B F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6436                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6437 0000290D 668B0B              <1> 	mov	cx, [ebx]
  6438                              <1> 	;
  6439                              <1> 	; 02/01/2015 
  6440                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6441                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6442 00002910 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6443                              <1> 	;
  6444 00002912 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6445 00002915 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6446 00002918 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6447                              <1> 	;SUB	AX,AX
  6448 0000291B 28C0                <1> 	sub	al, al
  6449 0000291D B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6450 0000291F 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6451                              <1> 	;POP	ES
  6452 00002920 1F                  <1> 	POP	DS
  6453 00002921 F8                  <1> 	CLC				; CLEAR CARRY
  6454                              <1> 	;RETf	2
  6455 00002922 CA0400              <1> 	retf	4
  6456                              <1> RDT_NOT_PRESENT:
  6457                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6458                              <1> 	; 05/12/2021
  6459 00002925 29C0                <1> 	sub	eax, eax
  6460                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6461                              <1> 	;MOV	DX,AX
  6462 00002927 89C1                <1> 	mov	ecx, eax
  6463 00002929 89C2                <1> 	mov	edx, eax
  6464 0000292B EBF2                <1> 	JMP	short RDT2
  6465                              <1> 
  6466                              <1> ;----------------------------------------
  6467                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6468                              <1> ;----------------------------------------
  6469                              <1> 
  6470                              <1> GET_PARM_N:
  6471                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6472 0000292D 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6473                              <1> 	;PUSH	ES
  6474 0000292E 53                  <1> 	PUSH	eBX
  6475                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6476                              <1> 	;MOV	DS,AX
  6477                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6478                              <1> 	;JZ	short G0
  6479                              <1> 	;LES	BX,@HF1_TBL_VEC
  6480                              <1> 	;JMP	SHORT G1
  6481                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6482                              <1> ;G1:
  6483                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6484                              <1> 	; 22/12/2014
  6485                              <1> 	;push	cs
  6486                              <1> 	;pop	ds
  6487 0000292F 66BB1000            <1> 	mov	bx, KDATA
  6488 00002933 8EDB                <1> 	mov	ds, bx
  6489                              <1> 	;mov	es, bx
  6490                              <1> 	;
  6491 00002935 80EA80              <1> 	SUB	DL,80H
  6492 00002938 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6493 0000293B 7340                <1> 	JAE	short G4
  6494                              <1> 	;
  6495 0000293D 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6496                              <1> 	; 22/12/2014
  6497 0000293F 88D3                <1> 	mov	bl, dl
  6498                              <1> 	;xor	bh, bh  
  6499 00002941 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6500                              <1> 	;add	bx, HF_TBL_VEC
  6501 00002944 81C3[34710000]      <1> 	add	ebx, HF_TBL_VEC
  6502                              <1> 	;mov	ax, [bx+2]
  6503                              <1> 	;mov	es, ax			; dpt segment
  6504                              <1> 	;mov	bx, [bx]		; dpt offset
  6505 0000294A 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6506                              <1> 
  6507 0000294C C605[2F710000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6508                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6509 00002953 668B03              <1> 	mov	ax, [ebx]
  6510                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6511 00002956 6648                <1> 	dec	ax			; max. cylinder number
  6512 00002958 88C5                <1> 	MOV	CH,AL
  6513 0000295A 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6514 0000295E 66D1E8              <1> 	SHR	AX,1
  6515 00002961 66D1E8              <1> 	SHR	AX,1
  6516                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6517 00002964 0A430E              <1> 	or	al, [ebx+14]
  6518 00002967 88C1                <1> 	MOV	CL,AL
  6519                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6520 00002969 8A7302              <1> 	mov	dh, [ebx+2]
  6521 0000296C FECE                <1> 	DEC	DH			; 0-N RANGE
  6522 0000296E 8A15[30710000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6523                              <1> 	;SUB	AX,AX
  6524                              <1> 	; 05/12/2021
  6525 00002974 29C0                <1> 	sub	eax, eax
  6526                              <1> 	; 27/12/2014 
  6527                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6528                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6529                              <1> 	;mov	di, bx			; HDPT offset
  6530 00002976 89DF                <1> 	mov	edi, ebx
  6531                              <1> G5:
  6532 00002978 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6533                              <1> 	;POP	ES
  6534 00002979 1F                  <1> 	POP	DS
  6535                              <1> 	;RETf	2
  6536 0000297A CA0400              <1> 	retf	4
  6537                              <1> G4:
  6538 0000297D C605[2F710000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6539                              <1> 	; 05/12/2021
  6540 00002984 29C0                <1> 	sub	eax, eax
  6541 00002986 B407                <1> 	MOV	AH,INIT_FAIL
  6542                              <1> 	;SUB	AL,AL
  6543                              <1> 	;SUB	DX,DX
  6544 00002988 29D2                <1> 	sub	edx, edx
  6545                              <1> 	;SUB	CX,CX
  6546 0000298A 29C9                <1> 	sub	ecx, ecx
  6547 0000298C F9                  <1> 	STC				; SET ERROR FLAG
  6548 0000298D EBE9                <1> 	JMP	short G5
  6549                              <1> 
  6550                              <1> ;----------------------------------------
  6551                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6552                              <1> ;----------------------------------------
  6553                              <1> 	; 03/01/2015
  6554                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6555                              <1> 	; logical sector per logical track
  6556                              <1> 	; and logical heads - 1 would be set but
  6557                              <1> 	; it is seen as it will be good
  6558                              <1> 	; if physical parameters will be set here
  6559                              <1> 	; because, number of heads <= 16.
  6560                              <1> 	; (logical heads usually more than 16)
  6561                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6562                              <1> 	;	== INT 13h physical parameters
  6563                              <1> 
  6564                              <1> ;INIT_DRV:
  6565                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6566                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6567                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6568                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6569                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6570                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6571                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6572                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6573                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6574                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6575                              <1> ;	SUB	AX,AX
  6576                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6577                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6578                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6579                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6580                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6581                              <1> ;	CALL	CHECK_STATUS
  6582                              <1> ;INIT_EXIT:
  6583                              <1> ;	RETn
  6584                              <1> 
  6585                              <1> ; 04/01/2015
  6586                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6587                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6588                              <1> INIT_DRV:
  6589                              <1> 	;xor	ah,ah
  6590 0000298F 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6591 00002991 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6592 00002993 3825[44710000]      <1>         cmp     [LBAMode], ah   ; 0
  6593 00002999 7702                <1> 	ja	short idrv0
  6594 0000299B B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6595                              <1> idrv0:
  6596                              <1> 	; DL = drive number (0 based)
  6597 0000299D E8BB030000          <1> 	call	GET_VEC
  6598                              <1> 	;push	bx
  6599 000029A2 53                  <1> 	push	ebx ; 21/02/2015
  6600                              <1> 	;add	bx,ax
  6601 000029A3 01C3                <1> 	add	ebx,eax
  6602                              <1> 	;; 05/01/2015
  6603 000029A5 8A25[886B0000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6604                              <1> 	;;and 	ah,1 
  6605 000029AB C0E404              <1> 	shl	ah,4
  6606 000029AE 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6607                              <1> 	;mov	al,[es:bx]
  6608 000029B1 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6609 000029B3 FEC8                <1> 	dec	al	 ; last head number 
  6610                              <1> 	;and	al,0Fh
  6611 000029B5 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6612                              <1> 	;
  6613 000029B7 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6614 000029BB 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6615                              <1> 	;pop	bx
  6616 000029BE 5B                  <1> 	pop	ebx
  6617 000029BF 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6618 000029C1 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6619 000029C3 803D[44710000]00    <1> 	cmp	byte [LBAMode],0
  6620 000029CA 7702                <1> 	ja	short idrv1
  6621 000029CC B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6622                              <1> idrv1:
  6623                              <1> 	;xor	ah,ah
  6624                              <1> 	;add	bx,ax
  6625 000029CE 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6626                              <1> 	;mov	al,[es:bx]
  6627                              <1> 			; sector number
  6628 000029D0 8A03                <1> 	mov	al,[ebx]
  6629 000029D2 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6630 000029D5 28C0                <1> 	sub	al,al
  6631 000029D7 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6632 000029DA E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6633 000029DF 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6634 000029E1 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6635 000029E6 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6636 000029E8 E8C3020000          <1> 	call	CHECK_STATUS
  6637                              <1> INIT_EXIT:
  6638 000029ED C3                  <1> 	RETn
  6639                              <1> 
  6640                              <1> ;----------------------------------------
  6641                              <1> ;	READ LONG	     (AH = 0AH) :
  6642                              <1> ;----------------------------------------
  6643                              <1> 
  6644                              <1> RD_LONG:
  6645                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6646 000029EE C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6647 000029F2 E9E0000000          <1>         JMP     COMMANDI
  6648                              <1> 
  6649                              <1> ;----------------------------------------
  6650                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6651                              <1> ;----------------------------------------
  6652                              <1> 
  6653                              <1> WR_LONG:
  6654                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6655 000029F7 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6656 000029FB E92C010000          <1>         JMP     COMMANDO
  6657                              <1> 
  6658                              <1> ;----------------------------------------
  6659                              <1> ;	SEEK		     (AH = 0CH) :
  6660                              <1> ;----------------------------------------
  6661                              <1> 
  6662                              <1> DISK_SEEK:
  6663 00002A00 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6664 00002A04 E89A010000          <1> 	CALL	COMMAND
  6665 00002A09 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6666 00002A0B E80C020000          <1> 	CALL	_WAIT
  6667 00002A10 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6668 00002A12 E899020000          <1> 	CALL	CHECK_STATUS
  6669 00002A17 803D[2F710000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6670 00002A1E 7507                <1> 	JNE	short DS_EXIT
  6671 00002A20 C605[2F710000]00    <1>         MOV     byte [DISK_STATUS1],0
  6672                              <1> DS_EXIT:
  6673 00002A27 C3                  <1> 	RETn
  6674                              <1> 
  6675                              <1> ;----------------------------------------
  6676                              <1> ;	TEST DISK READY      (AH = 10H) :
  6677                              <1> ;----------------------------------------
  6678                              <1> 
  6679                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6680 00002A28 E82B020000          <1> 	CALL	NOT_BUSY
  6681 00002A2D 751C                <1> 	JNZ	short TR_EX
  6682 00002A2F 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6683 00002A32 668B15[846B0000]    <1> 	MOV	DX,[HF_PORT]
  6684 00002A39 80C206              <1> 	add	dl,6
  6685 00002A3C EE                  <1> 	OUT	DX,AL
  6686 00002A3D E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6687 00002A42 7507                <1> 	JNZ	short TR_EX
  6688 00002A44 C605[2F710000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6689                              <1> TR_EX:	
  6690 00002A4B C3                  <1> 	RETn
  6691                              <1> 
  6692                              <1> ;----------------------------------------
  6693                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6694                              <1> ;----------------------------------------
  6695                              <1> 
  6696                              <1> HDISK_RECAL:
  6697 00002A4C C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6698 00002A50 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6699 00002A55 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6700 00002A57 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6701 00002A5C 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6702 00002A5E E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6703 00002A63 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6704                              <1> RECAL_X:
  6705 00002A65 E846020000          <1> 	CALL	CHECK_STATUS
  6706 00002A6A 803D[2F710000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6707 00002A71 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6708 00002A73 C605[2F710000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6709                              <1> RECAL_EXIT:
  6710 00002A7A 803D[2F710000]00    <1>         CMP     byte [DISK_STATUS1],0
  6711 00002A81 C3                  <1> 	RETn
  6712                              <1> 
  6713                              <1> ;----------------------------------------
  6714                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6715                              <1> ;----------------------------------------
  6716                              <1> 
  6717                              <1> CTLR_DIAGNOSTIC:
  6718 00002A82 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6719 00002A83 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6720                              <1> 	;AND	AL,0BFH
  6721 00002A85 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6722                              <1> 	;JMP	$+2
  6723                              <1> 	IODELAY
  2144 00002A87 EB00                <2>  jmp short $+2
  2145 00002A89 EB00                <2>  jmp short $+2
  6724 00002A8B E6A1                <1> 	OUT	INTB01,AL
  6725                              <1> 	IODELAY
  2144 00002A8D EB00                <2>  jmp short $+2
  2145 00002A8F EB00                <2>  jmp short $+2
  6726 00002A91 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6727 00002A93 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6728                              <1> 	;JMP	$+2
  6729                              <1> 	IODELAY
  2144 00002A95 EB00                <2>  jmp short $+2
  2145 00002A97 EB00                <2>  jmp short $+2
  6730 00002A99 E621                <1> 	OUT	INTA01,AL
  6731 00002A9B FB                  <1> 	STI
  6732 00002A9C E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6733 00002AA1 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6734                              <1> 	;MOV	DX, HF_PORT+7
  6735 00002AA3 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  6736 00002AAA 80C207              <1> 	add	dl, 7
  6737 00002AAD B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6738 00002AAF EE                  <1> 	OUT	DX,AL
  6739 00002AB0 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6740 00002AB5 B480                <1> 	MOV	AH,TIME_OUT
  6741 00002AB7 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6742                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6743 00002AB9 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  6744 00002AC0 FEC2                <1> 	inc	dl
  6745 00002AC2 EC                  <1> 	IN	AL,DX
  6746 00002AC3 A2[26710000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6747 00002AC8 B400                <1> 	MOV	AH,0
  6748 00002ACA 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6749 00002ACC 7402                <1> 	JE	SHORT CD_EXIT
  6750 00002ACE B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6751                              <1> CD_EXIT:
  6752 00002AD0 8825[2F710000]      <1> 	MOV	[DISK_STATUS1],AH
  6753 00002AD6 C3                  <1> 	RETn
  6754                              <1> 
  6755                              <1> ;----------------------------------------
  6756                              <1> ; COMMANDI				:
  6757                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6758                              <1> ;	NSECTOR RETURNS ZERO		:
  6759                              <1> ;----------------------------------------
  6760                              <1> COMMANDI:
  6761 00002AD7 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6762 00002ADC 724D                <1> 	JC	short CMD_ABORT
  6763                              <1> 	;MOV	DI,BX
  6764 00002ADE 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6765 00002AE0 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6766 00002AE5 7544                <1> 	JNZ	short CMD_ABORT
  6767                              <1> CMD_I1:
  6768 00002AE7 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6769 00002AEC 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6770                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6771 00002AEE B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6772                              <1> 	;MOV	DX,HF_PORT
  6773 00002AF3 668B15[846B0000]    <1> 	mov	dx,[HF_PORT]
  6774 00002AFA FA                  <1> 	CLI
  6775 00002AFB FC                  <1> 	CLD
  6776 00002AFC F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6777 00002AFF FB                  <1> 	STI
  6778 00002B00 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6779 00002B04 7419                <1> 	JZ	CMD_I3
  6780 00002B06 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6781 00002B0B 721E                <1> 	JC	short TM_OUT
  6782                              <1> 	;MOV	DX,HF_PORT
  6783 00002B0D 668B15[846B0000]    <1> 	mov	dx,[HF_PORT]
  6784                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6785 00002B14 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6786 00002B19 EC                  <1> CMD_I2: IN	AL,DX
  6787                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6788 00002B1A 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6789 00002B1C 47                  <1> 	INC	eDI
  6790 00002B1D E2FA                <1> 	LOOP	CMD_I2
  6791 00002B1F E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6792 00002B24 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6793 00002B26 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6794 00002B29 75BC                <1> 	JNZ	SHORT CMD_I1
  6795                              <1> CMD_ABORT:
  6796 00002B2B C3                  <1> TM_OUT: RETn
  6797                              <1> 
  6798                              <1> ;----------------------------------------
  6799                              <1> ; COMMANDO				:
  6800                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6801                              <1> ;	NSECTOR RETURNS ZERO		:
  6802                              <1> ;----------------------------------------
  6803                              <1> COMMANDO:
  6804 00002B2C E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6805 00002B31 72F8                <1> 	JC	short CMD_ABORT
  6806 00002B33 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6807 00002B35 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6808 00002B3A 75EF                <1> 	JNZ	short CMD_ABORT
  6809 00002B3C E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6810 00002B41 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6811                              <1> CMD_O1: ;PUSH	DS
  6812                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6813                              <1> 	;POP	DS
  6814                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6815                              <1> 	;MOV	DX,HF_PORT
  6816                              <1> 	; 01/02/2015
  6817 00002B43 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  6818                              <1> 	;push	es
  6819                              <1> 	;pop	ds
  6820                              <1> 	;mov	cx, 256
  6821 00002B4A B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6822 00002B4F FA                  <1> 	CLI
  6823 00002B50 FC                  <1> 	CLD
  6824 00002B51 F3666F              <1> 	REP	OUTSW
  6825 00002B54 FB                  <1> 	STI
  6826                              <1> 	;POP	DS			; RESTORE DS
  6827 00002B55 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6828 00002B59 7419                <1> 	JZ	short CMD_O3
  6829 00002B5B E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6830 00002B60 72C9                <1> 	JC	short TM_OUT
  6831                              <1> 	;MOV	DX,HF_PORT
  6832 00002B62 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  6833                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6834 00002B69 B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6835                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6836 00002B6E 8A06                <1> 	mov	al, [esi]
  6837 00002B70 EE                  <1> 	OUT	DX,AL
  6838 00002B71 46                  <1> 	INC	eSI
  6839 00002B72 E2FA                <1> 	LOOP	CMD_O2
  6840                              <1> CMD_O3:
  6841 00002B74 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6842 00002B79 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6843 00002B7B E830010000          <1> 	CALL	CHECK_STATUS
  6844 00002B80 75A9                <1> 	JNZ	short CMD_ABORT
  6845 00002B82 F605[25710000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6846 00002B89 75B8                <1> 	JNZ	SHORT CMD_O1
  6847                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6848 00002B8B 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  6849                              <1> 	;add	dl, 2
  6850 00002B92 FEC2                <1> 	inc	dl
  6851 00002B94 FEC2                <1> 	inc	dl
  6852 00002B96 EC                  <1> 	IN	AL,DX			;
  6853 00002B97 A8FF                <1> 	TEST	AL,0FFH 		;
  6854 00002B99 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6855 00002B9B C605[2F710000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6856                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6857                              <1> CMD_O4:
  6858 00002BA2 C3                  <1> 	RETn
  6859                              <1> 
  6860                              <1> ;--------------------------------------------------------
  6861                              <1> ; COMMAND						:
  6862                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6863                              <1> ; OUTPUT						:
  6864                              <1> ;	BL = STATUS					:
  6865                              <1> ;	BH = ERROR REGISTER				:
  6866                              <1> ;--------------------------------------------------------
  6867                              <1> 
  6868                              <1> COMMAND:
  6869 00002BA3 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6870                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6871                              <1> COMMAND1:
  6872                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6873 00002BA4 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6874                              <1> 	;;POP	CX
  6875 00002BA9 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6876 00002BAB 803D[2F710000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6877                              <1> 	;JZ	short CMD_TIMEOUT
  6878                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6879                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6880 00002BB2 7507                <1> 	jne	short COMMAND4
  6881                              <1> CMD_TIMEOUT:
  6882 00002BB4 C605[2F710000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6883                              <1> COMMAND4:
  6884 00002BBB 5B                  <1> 	POP	eBX
  6885 00002BBC 803D[2F710000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6886 00002BC3 C3                  <1> 	RETn
  6887                              <1> COMMAND2:
  6888 00002BC4 5B                  <1> 	POP	eBX
  6889 00002BC5 57                  <1> 	PUSH	eDI
  6890 00002BC6 C605[27710000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6891 00002BCD FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6892 00002BCE E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6893                              <1> 	;AND	AL,0BFH
  6894 00002BD0 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6895                              <1> 	;JMP	$+2
  6896                              <1> 	IODELAY
  2144 00002BD2 EB00                <2>  jmp short $+2
  2145 00002BD4 EB00                <2>  jmp short $+2
  6897 00002BD6 E6A1                <1> 	OUT	INTB01,AL
  6898 00002BD8 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6899 00002BDA 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6900                              <1> 	;JMP	$+2
  6901                              <1> 	IODELAY
  2144 00002BDC EB00                <2>  jmp short $+2
  2145 00002BDE EB00                <2>  jmp short $+2
  6902 00002BE0 E621                <1> 	OUT	INTA01,AL
  6903 00002BE2 FB                  <1> 	STI
  6904 00002BE3 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6905                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6906 00002BE5 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  6907 00002BEC FEC2                <1> 	inc	dl
  6908 00002BEE F605[31710000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6909 00002BF5 7411                <1> 	JZ	short COMMAND3
  6910 00002BF7 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6911 00002BFA 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6912 00002BFC 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6913 00002BFE 7208                <1> 	JB	short COMMAND3
  6914 00002C00 3C40                <1> 	CMP	AL,40H
  6915 00002C02 7704                <1> 	JA	short COMMAND3
  6916 00002C04 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6917                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6918                              <1> COMMAND3:
  6919 00002C08 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6920 00002C0C EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6921                              <1> 	IODELAY
  2144 00002C0D EB00                <2>  jmp short $+2
  2145 00002C0F EB00                <2>  jmp short $+2
  6922 00002C11 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6923 00002C12 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6924 00002C14 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6925 00002C18 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6926 00002C1A 5F                  <1> 	POP	eDI
  6927 00002C1B C3                  <1> 	RETn				; ZERO FLAG IS SET
  6928                              <1> 
  6929                              <1> ;CMD_TIMEOUT:
  6930                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6931                              <1> ;COMMAND4:
  6932                              <1> ;	POP	BX
  6933                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6934                              <1> ;	RETn
  6935                              <1> 
  6936                              <1> ;----------------------------------------
  6937                              <1> ;	WAIT FOR INTERRUPT		:
  6938                              <1> ;----------------------------------------
  6939                              <1> ;WAIT:
  6940                              <1> _WAIT:
  6941 00002C1C FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6942                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6943                              <1> 	;CLC
  6944                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6945                              <1> 	;INT	15H
  6946                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6947                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6948                              <1> 
  6949                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6950                              <1> 	;; 21/02/2015
  6951                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6952                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6953 00002C1D B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6954                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6955                              <1> ;-----	WAIT LOOP
  6956                              <1> 
  6957                              <1> WT1:	
  6958                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6959 00002C22 F605[27710000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6960                              <1> 	;LOOPZ	WT1
  6961 00002C29 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6962                              <1> 	;DEC	BL
  6963                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6964                              <1> 
  6965                              <1> WT1_hi:
  6966 00002C2B E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6967 00002C2D A810                <1> 	test	al, 10h			; transition on memory
  6968 00002C2F 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6969                              <1> WT1_lo:
  6970 00002C31 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6971 00002C33 A810                <1> 	test	al, 10h			
  6972 00002C35 74FA                <1> 	jz	short WT1_lo
  6973 00002C37 E2E9                <1> 	loop	WT1
  6974                              <1> 	;;or	bl, bl
  6975                              <1> 	;;jz	short WT2	
  6976                              <1> 	;;dec	bl
  6977                              <1> 	;;jmp	short WT1
  6978                              <1> 	;dec	bl
  6979                              <1> 	;jnz	short WT1	
  6980                              <1> 
  6981 00002C39 C605[2F710000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6982 00002C40 EB0E                <1> 	JMP	SHORT WT4
  6983 00002C42 C605[2F710000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6984 00002C49 C605[27710000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6985 00002C50 803D[2F710000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6986 00002C57 C3                  <1> 	RETn
  6987                              <1> 
  6988                              <1> ;----------------------------------------
  6989                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6990                              <1> ;----------------------------------------
  6991                              <1> NOT_BUSY:
  6992 00002C58 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6993                              <1> 	;PUSH	eBX
  6994                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6995 00002C59 668B15[846B0000]    <1> 	mov	DX, [HF_PORT]
  6996 00002C60 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6997                              <1> 	;MOV	BL,DELAY_1
  6998                              <1> 					; wait for 10 seconds
  6999                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  7000                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  7001                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  7002 00002C63 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  7003                              <1> 	;
  7004                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  7005                              <1> NB1:	
  7006 00002C68 EC                  <1> 	IN	AL,DX			; CHECK STATUS
  7007                              <1> 	;TEST	AL,ST_BUSY
  7008 00002C69 2480                <1> 	and	al, ST_BUSY
  7009                              <1> 	;LOOPNZ	NB1
  7010 00002C6B 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  7011                              <1> 	;DEC	BL			
  7012                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  7013                              <1> 
  7014 00002C6D E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  7015 00002C6F A810                <1> 	TEST	AL,010H			; transition on memory
  7016 00002C71 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  7017 00002C73 E461                <1> NB1_lo: IN	AL,SYS1
  7018 00002C75 A810                <1> 	TEST	AL,010H
  7019 00002C77 74FA                <1> 	JZ	short NB1_lo
  7020 00002C79 E2ED                <1> 	LOOP	NB1
  7021                              <1> 	;dec	bl
  7022                              <1> 	;jnz	short NB1
  7023                              <1> 	;
  7024                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  7025                              <1> ;;	jb	short NB1
  7026                              <1> 	;
  7027                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  7028                              <1> 	;JMP	SHORT NB3
  7029 00002C7B B080                <1> 	mov	al, TIME_OUT
  7030                              <1> NB2:	
  7031                              <1> 	;MOV	byte [DISK_STATUS1],0
  7032                              <1> ;NB3:	
  7033                              <1> 	;POP	eBX
  7034 00002C7D A2[2F710000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  7035                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  7036 00002C82 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  7037 00002C84 C3                  <1> 	RETn
  7038                              <1> 
  7039                              <1> ;----------------------------------------
  7040                              <1> ;	WAIT FOR DATA REQUEST		:
  7041                              <1> ;----------------------------------------
  7042                              <1> WAIT_DRQ:
  7043                              <1> 	;MOV	CX,DELAY_3
  7044                              <1> 	;MOV	DX,HF_PORT+7
  7045 00002C85 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  7046 00002C8C 80C207              <1> 	add	dl, 7
  7047                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7048                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7049                              <1> 					; (but it is written as 2000
  7050                              <1> 					; micro seconds in ATORGS.ASM file
  7051                              <1> 					; of Award Bios - 1999, D1A0622)
  7052 00002C8F B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7053 00002C94 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7054 00002C95 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7055 00002C97 7516                <1> 	JNZ	short WQ_OK
  7056                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7057                              <1> WQ_hi:	
  7058 00002C99 E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7059 00002C9B A810                <1> 	TEST	AL,010H			; transition on memory
  7060 00002C9D 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7061 00002C9F E461                <1> WQ_lo:  IN      AL,SYS1
  7062 00002CA1 A810                <1> 	TEST	AL,010H
  7063 00002CA3 74FA                <1> 	JZ	SHORT WQ_lo
  7064 00002CA5 E2ED                <1> 	LOOP	WQ_1
  7065                              <1> 
  7066 00002CA7 C605[2F710000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7067 00002CAE F9                  <1> 	STC
  7068                              <1> WQ_OK:
  7069 00002CAF C3                  <1> 	RETn
  7070                              <1> ;WQ_OK:	;CLC
  7071                              <1> ;	RETn
  7072                              <1> 
  7073                              <1> ;----------------------------------------
  7074                              <1> ;	CHECK FIXED DISK STATUS 	:
  7075                              <1> ;----------------------------------------
  7076                              <1> CHECK_STATUS:
  7077 00002CB0 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7078 00002CB5 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7079 00002CB7 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7080 00002CB9 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7081 00002CBB E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7082                              <1> CHECK_S1:
  7083 00002CC0 803D[2F710000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7084 00002CC7 C3                  <1> 	RETn
  7085                              <1> 
  7086                              <1> ;----------------------------------------
  7087                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7088                              <1> ;----------------------------------------
  7089                              <1> CHECK_ST:
  7090                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7091 00002CC8 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]
  7092 00002CCF 80C207              <1> 	add	dl, 7
  7093 00002CD2 EC                  <1> 	IN	AL,DX
  7094 00002CD3 A2[25710000]        <1> 	MOV	[HF_STATUS],AL
  7095 00002CD8 B400                <1> 	MOV	AH,0
  7096 00002CDA A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7097 00002CDC 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7098 00002CDE B4CC                <1> 	MOV	AH,WRITE_FAULT
  7099 00002CE0 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7100 00002CE2 7514                <1> 	JNZ	short CKST_EXIT
  7101 00002CE4 B4AA                <1> 	MOV	AH,NOT_RDY
  7102 00002CE6 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7103 00002CE8 740E                <1> 	JZ	short CKST_EXIT
  7104 00002CEA B440                <1> 	MOV	AH,BAD_SEEK
  7105 00002CEC A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7106 00002CEE 7408                <1> 	JZ	short CKST_EXIT
  7107 00002CF0 B411                <1> 	MOV	AH,DATA_CORRECTED
  7108 00002CF2 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7109 00002CF4 7502                <1> 	JNZ	short CKST_EXIT
  7110 00002CF6 B400                <1> 	MOV	AH,0
  7111                              <1> CKST_EXIT:
  7112 00002CF8 8825[2F710000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7113 00002CFE 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7114 00002D01 7403                <1> 	JZ	short CKST_EX1
  7115 00002D03 80FC00              <1> 	CMP	AH,0
  7116                              <1> CKST_EX1:
  7117 00002D06 C3                  <1> 	RETn
  7118                              <1> 
  7119                              <1> ;----------------------------------------
  7120                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7121                              <1> ;----------------------------------------
  7122                              <1> CHECK_ER:
  7123                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7124 00002D07 668B15[846B0000]    <1> 	mov	dx, [HF_PORT]		;
  7125 00002D0E FEC2                <1> 	inc	dl
  7126 00002D10 EC                  <1> 	IN	AL,DX
  7127 00002D11 A2[26710000]        <1> 	MOV	[HF_ERROR],AL
  7128 00002D16 53                  <1> 	PUSH	eBX ; 21/02/2015
  7129 00002D17 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7130 00002D1C D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7131 00002D1E 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7132 00002D20 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7133 00002D22 BB[786B0000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7134 00002D27 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7135                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7136                              <1> 	;mov	ah, [bx]
  7137 00002D29 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7138 00002D2B 8825[2F710000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7139 00002D31 5B                  <1> 	POP	eBX
  7140 00002D32 80FC00              <1> 	CMP	AH,0
  7141 00002D35 C3                  <1> 	RETn
  7142                              <1> 
  7143                              <1> ;--------------------------------------------------------
  7144                              <1> ; CHECK_DMA						:
  7145                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7146                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7147                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7148                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7149                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7150                              <1> ;  -ERROR OTHERWISE					:
  7151                              <1> ;--------------------------------------------------------
  7152                              <1> CHECK_DMA:
  7153                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7154                              <1> 	; 05/12/2021
  7155 00002D36 50                  <1> 	push	eax
  7156 00002D37 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7157 00002D3B F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7158 00002D3F 7404                <1> 	JZ	short CKD1
  7159 00002D41 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7160 00002D45 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7161 00002D48 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7162 00002D4A 7207                <1> 	JB	short CKDERR		; TOO MANY
  7163 00002D4C 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7164 00002D4E 7203                <1> 	JB	short CKDERR		; ERROR
  7165 00002D50 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7166                              <1> 	;POP	AX
  7167                              <1> 	; 05/12/2021
  7168 00002D51 58                  <1> 	pop	eax
  7169 00002D52 C3                  <1> 	RETn				; NORMAL RETURN
  7170 00002D53 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7171 00002D54 C605[2F710000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7172                              <1> 	;POP	AX
  7173                              <1> 	; 05/12/2021
  7174 00002D5B 58                  <1> 	pop	eax	
  7175 00002D5C C3                  <1> 	RETn
  7176                              <1> 
  7177                              <1> ;----------------------------------------
  7178                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7179                              <1> ;----------------------------------------
  7180                              <1> 					
  7181                              <1> ; INPUT -> DL = 0 based drive number
  7182                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7183                              <1> 
  7184                              <1> GET_VEC:
  7185                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7186                              <1> 	;MOV	ES,AX
  7187                              <1> 	;TEST	DL,1
  7188                              <1> 	;JZ	short GV_0
  7189                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7190                              <1> ;	JMP	SHORT GV_EXIT
  7191                              <1> ;GV_0:
  7192                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7193                              <1> ;
  7194                              <1> 	;xor	bh, bh
  7195 00002D5D 31DB                <1> 	xor	ebx, ebx
  7196 00002D5F 88D3                <1> 	mov	bl, dl
  7197                              <1> 	;;02/01/2015
  7198                              <1> 	;;shl	bl, 1			; port address offset
  7199                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7200                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7201 00002D61 C0E302              <1> 	shl	bl, 2	;;
  7202                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7203 00002D64 81C3[34710000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7204                              <1> 	;push	word [bx+2]		; dpt segment
  7205                              <1> 	;pop	es
  7206                              <1> 	;mov	bx, [bx]		; dpt offset
  7207 00002D6A 8B1B                <1> 	mov	ebx, [ebx]		
  7208                              <1> ;GV_EXIT:
  7209 00002D6C C3                  <1> 	RETn
  7210                              <1> 
  7211                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7212                              <1> hdc1_int: ; 21/02/2015
  7213                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7214                              <1> ;								:
  7215                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7216                              <1> ;								:
  7217                              <1> ;----------------------------------------------------------------
  7218                              <1> 
  7219                              <1> ; 22/12/2014
  7220                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7221                              <1> ;	 '11/15/85'
  7222                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7223                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7224                              <1> 
  7225                              <1> ;int_76h:
  7226                              <1> HD_INT:
  7227                              <1> 	;push	ax
  7228                              <1> 	; 05/12/2021
  7229 00002D6D 50                  <1> 	push	eax
  7230 00002D6E 1E                  <1> 	push	ds
  7231                              <1> 	;CALL	DDS
  7232                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7233 00002D6F 66B81000            <1> 	mov	ax, KDATA
  7234 00002D73 8ED8                <1> 	mov 	ds, ax
  7235                              <1> 	;
  7236                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7237                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7238 00002D75 C605[27710000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7239                              <1> 	;
  7240                              <1> 	;push	dx
  7241                              <1> 	; 05/12/2021
  7242 00002D7C 52                  <1> 	push	edx
  7243 00002D7D 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7244                              <1> 					; Clear Controller
  7245                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7246 00002D81 EC                  <1> 	in	al, dx			;
  7247                              <1> 	;pop	dx
  7248                              <1> 	; 05/12/2021
  7249 00002D82 5A                  <1> 	pop	edx
  7250                              <1> 	NEWIODELAY
  2149 00002D83 E6EB                <2>  out 0EBh,al
  7251                              <1> 	;
  7252 00002D85 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7253 00002D87 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7254                              <1> 	;JMP	$+2			; WAIT
  7255                              <1> 	NEWIODELAY
  2149 00002D89 E6EB                <2>  out 0EBh,al
  7256 00002D8B E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7257 00002D8D 1F                  <1> 	pop	ds
  7258                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7259                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7260                              <1> 	;INT	15H			;  INTERRUPT
  7261                              <1> irq15_iret: ; 25/02/2015
  7262                              <1> 	;pop	ax
  7263                              <1> 	; 05/12/2021
  7264 00002D8E 58                  <1> 	pop	eax
  7265 00002D8F CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7266                              <1> 
  7267                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7268                              <1> hdc2_int: ; 21/02/2015
  7269                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7270                              <1> ;								:
  7271                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7272                              <1> ;								:
  7273                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7274                              <1> 
  7275                              <1> ;int_77h:
  7276                              <1> HD1_INT:
  7277                              <1> 	;push	ax
  7278                              <1> 	; 05/12/2021
  7279 00002D90 50                  <1> 	push	eax
  7280                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7281                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7282 00002D91 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7283 00002D93 E6A0                <1> 	out	0A0h, al
  7284 00002D95 EB00                <1>         jmp short $+2
  7285 00002D97 EB00                <1> 	jmp short $+2
  7286 00002D99 E4A0                <1> 	in	al, 0A0h
  7287 00002D9B 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7288 00002D9D 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7289                              <1> 	;
  7290 00002D9F 1E                  <1> 	push	ds
  7291                              <1> 	;CALL	DDS
  7292                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7293 00002DA0 66B81000            <1> 	mov	ax, KDATA
  7294 00002DA4 8ED8                <1> 	mov 	ds, ax
  7295                              <1> 	;
  7296                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7297                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7298 00002DA6 800D[27710000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7299                              <1> 	;
  7300                              <1> 	;push	dx
  7301                              <1> 	; 05/12/2021
  7302 00002DAD 52                  <1> 	push	edx
  7303 00002DAE 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7304                              <1> 					; Clear Controller (Award BIOS 1999)
  7305 00002DB2 EBCD                <1> 	jmp	short Clear_IRQ1415
  7306                              <1> 
  7307                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7308                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7309                              <1> 
  7310                              <1> ;////////////////////////////////////////////////////////////////////
  7311                              <1> ;; END OF DISK I/O SYTEM ///
  2084                                  %include 'memory.s'  ; 09/03/2015
  2085                              <1> ; Retro UNIX 386 v2 - memory.s - 26/01/2020
  2086                              <1> ; Last Modification: 31/12/2021 (Retro UNIX 386 v1.2)
  2087                              <1> ; ----------------------------------------------------------------------------
  2088                              <1> ;
  2089                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2090                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC
  2091                              <1> ; 18/10/2015 (!not completed!)
  2092                              <1> ;
  2093                              <1> ; Source code for NASM - Netwide Assembler (2.11)
  2094                              <1> 
  2095                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2096                              <1> 
  2097                              <1> ;;04/11/2014 (unix386.s)	
  2098                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2099                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2100                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2101                              <1> ;;
  2102                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2103                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2104                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2105                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2106                              <1> 
  2107                              <1> ; 27/04/2015
  2108                              <1> ; 09/03/2015
  2109                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2110                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2111                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2112                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2113                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2114                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2115                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2116                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2117                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2118                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2119                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2120                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2121                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2122                              <1> SWP_DISK_READ_ERR 	   equ 40
  2123                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2124                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2125                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2126                              <1> SWP_DISK_WRITE_ERR         equ 44
  2127                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2128                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2129                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2130                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2131                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2132                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2133                              <1> 					; (Indicates that the page is not allocated
  2134                              <1> 					; for the process, it is a shared or system
  2135                              <1>                                         ; page, it must not be deallocated!)
  2136                              <1> ; 14/12/2020
  2137                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2138                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2139                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2140                              <1> 				; (Out of memory allocation table)	
  2141                              <1> ;
  2142                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2143                              <1> ;;
  2144                              <1> ;; 10/10/2014
  2145                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2146                              <1> ;;
  2147                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2148                              <1> ;;	(virtual address = physical address)
  2149                              <1> ;; KERNEL PAGE TABLES:
  2150                              <1> ;;	Kernel page directory and all page tables are
  2151                              <1> ;;	on memory as initialized, as equal to physical memory
  2152                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2153                              <1> ;;
  2154                              <1> ;;	what for: User pages may be swapped out, when accessing
  2155                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2156                              <1> ;;	kernel would have to swap it in! But it is also may be
  2157                              <1> ;;	in use by a user process. (In system/kernel mode
  2158                              <1> ;;	kernel can access all memory pages even if they are
  2159                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2160                              <1> ;;	cause conflicts.) 
  2161                              <1> ;;	
  2162                              <1> ;;	As result of these conditions,
  2163                              <1> ;;	all kernel pages must be initialized as equal to 
  2164                              <1> ;;	physical layout for preventing page faults. 
  2165                              <1> ;;	Also, calling "allocate page" procedure after
  2166                              <1> ;;	a page fault can cause another page fault (double fault)
  2167                              <1> ;;	if all kernel page tables would not be initialized.
  2168                              <1> ;;
  2169                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2170                              <1> ;;	memory allocation table. (double word aligned)
  2171                              <1> ;;
  2172                              <1> ;;	[next_page] = first/next free space to be searched
  2173                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2174                              <1> ;;
  2175                              <1> ;;	[last_page] = End of memory (users space), as offset
  2176                              <1> ;;	to memory allocation table. (double word aligned)
  2177                              <1> ;;
  2178                              <1> ;; USER PAGE TABLES:
  2179                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2180                              <1> ;;		'ready only' marked copies of the 
  2181                              <1> ;;		parent process's page table entries (for
  2182                              <1> ;;		same physical memory).
  2183                              <1> ;;		(A page will be copied to a new page after
  2184                              <1> ;;		 if it causes R/W page fault.)
  2185                              <1> ;;
  2186                              <1> ;;	Every user process has own (different)
  2187                              <1> ;;	page directory and page tables.	
  2188                              <1> ;;
  2189                              <1> ;;	Code starts at virtual address 0, always.
  2190                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2191                              <1> ;;	(Programs can be written/developed as simple
  2192                              <1> ;;	 flat memory programs.)
  2193                              <1> ;;
  2194                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2195                              <1> ;;	Memory page will be allocated by kernel only 
  2196                              <1> ;;		(in kernel/system mode only).
  2197                              <1> ;;	* After a
  2198                              <1> ;;	  - 'not present' page fault
  2199                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2200                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2201                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2202                              <1> ;;	  request by running process.
  2203                              <1> ;;	* While creating a process, allocating a new buffer,
  2204                              <1> ;;	  new page tables etc.
  2205                              <1> ;;
  2206                              <1> ;;	At first,
  2207                              <1> ;;	- 'allocate page' procedure will be called;
  2208                              <1> ;,	   if it will return with a valid (>0) physical address
  2209                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2210                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2211                              <1> ;;	- 'allocate page' will be called for allocating page
  2212                              <1> ;;	   directory, page table and running space (data/code).
  2213                              <1> ;;	- every successful 'allocate page' call will decrease
  2214                              <1> ;;	  'free_pages' count (pointer).
  2215                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2216                              <1> ;;	  if 'free_pages' points to a ZERO.
  2217                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2218                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2219                              <1> ;;	  error except errors caused by attribute conflicts.
  2220                              <1> ;;	 (swapper functions)	 
  2221                              <1> ;;					
  2222                              <1> ;;	At second,
  2223                              <1> ;;	- page directory entry will be updated then page table
  2224                              <1> ;;	  entry will be updated.		
  2225                              <1> ;;
  2226                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2227                              <1> ;;	- M.A.T. has a size according to available memory as
  2228                              <1> ;;	  follows:
  2229                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2230                              <1> ;;		  - a bit with value of 0 means allocated page
  2231                              <1> ;;		  - a bit with value of 1 means a free page
  2232                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2233                              <1> ;;	  depending on M.A.T.
  2234                              <1> ;;		(NOTE: Free page count will not be checked
  2235                              <1> ;;		again -on M.A.T.- after initialization. 
  2236                              <1> ;;		Kernel will trust on initial count.)
  2237                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2238                              <1> ;;	  and it will be increased by deallocation procedures.
  2239                              <1> ;;	
  2240                              <1> ;;	- Available memory will be calculated during
  2241                              <1> ;;	  the kernel's initialization stage (in real mode).
  2242                              <1> ;;	  Memory allocation table and kernel page tables 
  2243                              <1> ;;	  will be formatted/sized as result of available
  2244                              <1> ;;	  memory calculation before paging is enabled.
  2245                              <1> ;;
  2246                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2247                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2248                              <1> ;;	- Memory allocation for kernel page directory size 
  2249                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2250                              <1> ;;	  for page tables)
  2251                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2252                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2253                              <1> ;;	- User (available) space will be started 
  2254                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2255                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2256                              <1> ;;	  memory allocation table and kernel's page directory
  2257                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2258                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2259                              <1> ;; 	  for buffers.
  2260                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2261                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2262                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2263                              <1> ;;
  2264                              <1> ;; For 1GB Available Memory:
  2265                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2266                              <1> ;;	- Memory allocation for kernel page directory size 
  2267                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2268                              <1> ;;	  for page tables)
  2269                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2270                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2271                              <1> ;;	- User (available) space will be started 
  2272                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2273                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2274                              <1> ;;	  memory allocation table and kernel's page directory
  2275                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2276                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2277                              <1> ;; 	  for buffers.
  2278                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2279                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2280                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2281                              <1> ;;
  2282                              <1> ;;
  2283                              <1> 
  2284                              <1> ;;************************************************************************************
  2285                              <1> ;; 
  2286                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2287                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2288                              <1> 
  2289                              <1> ;; Main factor: "sys fork" system call 
  2290                              <1> ;;	
  2291                              <1> ;; 		FORK
  2292                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2293                              <1> ;;  writable pages ---->|
  2294                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2295                              <1> ;; 
  2296                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2297                              <1> ;; 
  2298                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2299                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2300                              <1> ;;       -while R/W bit is 0-. 
  2301                              <1> ;; 
  2302                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2303                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2304                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2305                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2306                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2307                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2308                              <1> ;; 
  2309                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2310                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2311                              <1> ;;   Parent's PTE attributes are not changed.
  2312                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2313                              <1> ;;    destroy/mix previous fork result).
  2314                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2315                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2316                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2317                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2318                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2319                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2320                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2321                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2322                              <1> ;; 
  2323                              <1> ;; !? WHAT FOR (duplication after duplication):
  2324                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2325                              <1> ;; program/executable code continues from specified location as child process, 
  2326                              <1> ;; returns back previous code location as parent process, every child after 
  2327                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2328                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2329                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2330                              <1> ;; was copied to child's process segment (all of code and data) according to
  2331                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2332                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2333                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2334                              <1> ;; (complete running image of parent process) to the child process; 
  2335                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2336                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2337                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2338                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2339                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2340                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2341                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2342                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2343                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2344                              <1> ;; for sharing same read only pages between parent and child processes.
  2345                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2346                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2347                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2348                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2349                              <1> ;; -deallocation problem-.
  2350                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2351                              <1> ;; 
  2352                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2353                              <1> ;; # Page fault handler will do those:
  2354                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2355                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2356                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2357                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2358                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2359                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2360                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2361                              <1> ;;     to child process.)	
  2362                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2363                              <1> ;; # Page fault handler will do those:
  2364                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2365                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2366                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2367                              <1> ;;     address or not. 
  2368                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2369                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2370                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2371                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2372                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2373                              <1> ;; 
  2374                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2375                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2376                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2377                              <1> ;;       duplication method details, it is not possible multiple child processes
  2378                              <1> ;;       were using same page with duplicated PTEs.
  2379                              <1> ;; 
  2380                              <1> ;;************************************************************************************   
  2381                              <1> 
  2382                              <1> ;; 08/10/2014
  2383                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2384                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2385                              <1> 
  2386                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2387                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2388                              <1> ;; (25/08/2014, Revision: 5057) file 
  2389                              <1> ;; by KolibriOS Team (2004-2012)
  2390                              <1> 
  2391                              <1> allocate_page:
  2392                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2393                              <1> 	;	 (temporary modifications)
  2394                              <1> 	; 01/07/2015
  2395                              <1> 	; 05/05/2015
  2396                              <1> 	; 30/04/2015
  2397                              <1> 	; 16/10/2014
  2398                              <1> 	; 08/10/2014
  2399                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2400                              <1> 	;
  2401                              <1> 	; INPUT -> none
  2402                              <1> 	;
  2403                              <1> 	; OUTPUT ->
  2404                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2405                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2406                              <1> 	;
  2407                              <1> 	;	CF = 1 and EAX = 0 
  2408                              <1> 	; 		   if there is not a free page to be allocated	
  2409                              <1> 	;
  2410                              <1> 	; Modified Registers -> none (except EAX)
  2411                              <1> 	;
  2412 00002DB4 A1[A0700000]        <1> 	mov	eax, [free_pages]
  2413 00002DB9 21C0                <1> 	and	eax, eax
  2414 00002DBB 7438                <1> 	jz	short out_of_memory
  2415                              <1> 	;
  2416 00002DBD 53                  <1> 	push	ebx
  2417 00002DBE 51                  <1> 	push	ecx
  2418                              <1> 	;
  2419 00002DBF BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2420 00002DC4 89D9                <1> 	mov	ecx, ebx
  2421                              <1>  				     ; NOTE: 32 (first_page) is initial
  2422                              <1> 				     ; value of [next_page].
  2423                              <1> 				     ; It points to the first available
  2424                              <1> 				     ; page block for users (ring 3) ...	
  2425                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2426                              <1> 				     ; (at the of the first 4 MB)		
  2427 00002DC6 031D[A4700000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2428                              <1> 				 ; next_free_page >> 5
  2429 00002DCC 030D[A8700000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2430                              <1> 				 ; (total_pages - 1) >> 5
  2431                              <1> al_p_scan:
  2432 00002DD2 39CB                <1> 	cmp	ebx, ecx
  2433 00002DD4 770A                <1> 	ja	short al_p_notfound
  2434                              <1> 	;
  2435                              <1> 	; 01/07/2015
  2436                              <1> 	; AMD64 Architecture Programmers Manual
  2437                              <1> 	; Volume 3:
  2438                              <1> 	; General-Purpose and System Instructions
  2439                              <1> 	;
  2440                              <1> 	; BSF - Bit Scan Forward
  2441                              <1> 	;
  2442                              <1> 	;   Searches the value in a register or a memory location
  2443                              <1> 	;   (second operand) for the least-significant set bit. 
  2444                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2445                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2446                              <1> 	;   register (first operand). If the second operand contains 0, 
  2447                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2448                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2449                              <1> 	;   of the searched value
  2450                              <1> 	;
  2451 00002DD6 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2452                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2453                              <1> 			   ; loads the destination with an index to
  2454                              <1> 			   ; first set bit. (0 -> 31) 
  2455                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2456 00002DD9 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2457                              <1> 			 ;
  2458                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2459                              <1> 			 ;	  with value of 1 means 
  2460                              <1> 			 ;	  the corresponding page is free 
  2461                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2462 00002DDB 83C304              <1> 	add	ebx, 4
  2463                              <1> 			 ; We return back for searching next page block
  2464                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2465                              <1> 			 ;	 we always will find at least 1 free page here.
  2466 00002DDE EBF2                <1>         jmp     short al_p_scan
  2467                              <1> 	;
  2468                              <1> al_p_notfound:
  2469 00002DE0 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2470 00002DE6 890D[A4700000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2471                              <1> 				 ; (deallocate_page procedure will change it)
  2472 00002DEC 31C0                <1> 	xor	eax, eax
  2473 00002DEE A3[A0700000]        <1> 	mov	[free_pages], eax ; 0
  2474 00002DF3 59                  <1> 	pop	ecx
  2475 00002DF4 5B                  <1> 	pop	ebx
  2476                              <1> 	;
  2477                              <1> ; 17/04/2021
  2478                              <1> ; ('swap_out' procedure call is disabled as temporary)
  2479                              <1> 
  2480                              <1> out_of_memory:
  2481                              <1> ;	call	swap_out
  2482                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2483                              <1> ;	;
  2484                              <1> ;	sub 	eax, eax ; 0
  2485 00002DF5 F9                  <1> 	stc
  2486 00002DF6 C3                  <1> 	retn
  2487                              <1> 
  2488                              <1> al_p_found:
  2489 00002DF7 89D9                <1> 	mov	ecx, ebx
  2490 00002DF9 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2491 00002DFF 890D[A4700000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2492                              <1> 				 ; address/offset (to the next)
  2493 00002E05 FF0D[A0700000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2494                              <1> 	;
  2495 00002E0B 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2496                              <1> 				 ; is copied into the Carry Flag and then cleared
  2497                              <1> 				 ; in the destination.
  2498                              <1> 				 ;
  2499                              <1> 				 ; Reset the bit which is corresponding to the 
  2500                              <1> 				 ; (just) allocated page.
  2501                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2502 00002E0E C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2503 00002E11 01C8                <1> 	add	eax, ecx	 ; = page number
  2504 00002E13 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2505                              <1> 	; EAX = physical address of memory page
  2506                              <1> 	;
  2507                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2508                              <1> 	;       according to this EAX value...
  2509 00002E16 59                  <1> 	pop	ecx
  2510 00002E17 5B                  <1> 	pop	ebx
  2511                              <1> al_p_ok:
  2512 00002E18 C3                  <1> 	retn
  2513                              <1> 
  2514                              <1> make_page_dir:
  2515                              <1> 	; 18/04/2015
  2516                              <1> 	; 12/04/2015
  2517                              <1> 	; 23/10/2014
  2518                              <1> 	; 16/10/2014
  2519                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2520                              <1> 	;
  2521                              <1> 	; INPUT ->
  2522                              <1> 	;	none
  2523                              <1> 	; OUTPUT ->
  2524                              <1> 	;	(EAX = 0)
  2525                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2526                              <1> 	;	cf = 0 ->
  2527                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2528                              <1> 	;		  process/user.
  2529                              <1> 	;
  2530                              <1> 	; Modified Registers -> EAX
  2531                              <1> 	;
  2532 00002E19 E896FFFFFF          <1> 	call	allocate_page
  2533 00002E1E 7216                <1> 	jc	short mkpd_error
  2534                              <1> 	;
  2535 00002E20 A3[0C760000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2536                              <1> 				  ; (Physical address)
  2537                              <1> clear_page:
  2538                              <1> 	; 18/04/2015
  2539                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2540                              <1> 	;
  2541                              <1> 	; INPUT ->
  2542                              <1> 	;	EAX = physical address of the page
  2543                              <1> 	; OUTPUT ->
  2544                              <1> 	;	all bytes of the page will be cleared
  2545                              <1> 	;
  2546                              <1> 	; Modified Registers -> none
  2547                              <1> 	;
  2548 00002E25 57                  <1> 	push	edi
  2549 00002E26 51                  <1> 	push	ecx
  2550 00002E27 50                  <1> 	push	eax
  2551 00002E28 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2552 00002E2D 89C7                <1> 	mov	edi, eax
  2553 00002E2F 31C0                <1> 	xor	eax, eax
  2554 00002E31 F3AB                <1> 	rep	stosd
  2555 00002E33 58                  <1> 	pop	eax
  2556 00002E34 59                  <1> 	pop	ecx
  2557 00002E35 5F                  <1> 	pop	edi
  2558                              <1> mkpd_error:
  2559                              <1> mkpt_error:
  2560 00002E36 C3                  <1> 	retn
  2561                              <1> 
  2562                              <1> make_page_table:
  2563                              <1> 	; 23/06/2015
  2564                              <1> 	; 18/04/2015
  2565                              <1> 	; 12/04/2015
  2566                              <1> 	; 16/10/2014
  2567                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2568                              <1> 	;
  2569                              <1> 	; INPUT ->
  2570                              <1> 	;	EBX = virtual (linear) address
  2571                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2572                              <1> 	;	      (higher 20 bits must be ZERO)
  2573                              <1> 	;	      (bit 0 must be 1)	 
  2574                              <1> 	;	u.pgdir = page directory (physical) address
  2575                              <1> 	; OUTPUT ->
  2576                              <1> 	;	EDX = Page directory entry address
  2577                              <1> 	;	EAX = Page table address
  2578                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2579                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2580                              <1> 	;
  2581                              <1> 	; Modified Registers -> EAX, EDX
  2582                              <1> 	;
  2583 00002E37 E878FFFFFF          <1> 	call	allocate_page
  2584 00002E3C 72F8                <1> 	jc	short mkpt_error
  2585 00002E3E E811000000          <1> 	call	set_pde	
  2586 00002E43 EBE0                <1> 	jmp	short clear_page
  2587                              <1> 
  2588                              <1> make_page:
  2589                              <1> 	; 24/07/2015
  2590                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2591                              <1> 	;
  2592                              <1> 	; INPUT ->
  2593                              <1> 	;	EBX = virtual (linear) address
  2594                              <1> 	;	ECX = page attributes (lower 12 bits)
  2595                              <1> 	;	      (higher 20 bits must be ZERO)
  2596                              <1> 	;	      (bit 0 must be 1)	 
  2597                              <1> 	;	u.pgdir = page directory (physical) address
  2598                              <1> 	; OUTPUT ->
  2599                              <1> 	;	EBX = Virtual address
  2600                              <1> 	;	(EDX = PTE value)
  2601                              <1> 	;	EAX = Physical address
  2602                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2603                              <1> 	;
  2604                              <1> 	; Modified Registers -> EAX, EDX
  2605                              <1> 	;
  2606 00002E45 E86AFFFFFF          <1> 	call	allocate_page
  2607 00002E4A 7207                <1> 	jc	short mkp_err
  2608 00002E4C E821000000          <1> 	call	set_pte	
  2609 00002E51 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2610                              <1> mkp_err:
  2611 00002E53 C3                  <1> 	retn
  2612                              <1> 
  2613                              <1> set_pde:	; Set page directory entry (PDE)
  2614                              <1> 	; 20/07/2015
  2615                              <1> 	; 18/04/2015
  2616                              <1> 	; 12/04/2015
  2617                              <1> 	; 23/10/2014
  2618                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2619                              <1> 	;
  2620                              <1> 	; INPUT ->
  2621                              <1> 	;	EAX = physical address
  2622                              <1> 	;	      (use present value if EAX = 0)
  2623                              <1> 	;	EBX = virtual (linear) address
  2624                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2625                              <1> 	;	      (higher 20 bits must be ZERO)
  2626                              <1> 	;	      (bit 0 must be 1)	 
  2627                              <1> 	;	u.pgdir = page directory (physical) address
  2628                              <1> 	; OUTPUT ->
  2629                              <1> 	;	EDX = PDE address
  2630                              <1> 	;	EAX = page table address (physical)
  2631                              <1> 	;	;(CF=1 -> Invalid page address)
  2632                              <1> 	;
  2633                              <1> 	; Modified Registers -> EDX
  2634                              <1> 	;
  2635 00002E54 89DA                <1> 	mov	edx, ebx
  2636 00002E56 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2637 00002E59 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2638 00002E5C 0315[0C760000]      <1> 	add	edx, [u.pgdir]
  2639                              <1> 	;
  2640 00002E62 21C0                <1> 	and	eax, eax
  2641 00002E64 7506                <1> 	jnz	short spde_1
  2642                              <1> 	;
  2643 00002E66 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2644                              <1> 	;test	al, 1
  2645                              <1> 	;jz	short spde_2
  2646 00002E68 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2647                              <1> spde_1:
  2648                              <1> 	;and	cx, 0FFFh
  2649 00002E6C 8902                <1> 	mov	[edx], eax
  2650 00002E6E 66090A              <1> 	or	[edx], cx
  2651 00002E71 C3                  <1> 	retn
  2652                              <1> ;spde_2: ; error
  2653                              <1> ;	stc
  2654                              <1> ;	retn
  2655                              <1> 
  2656                              <1> set_pte:	; Set page table entry (PTE)
  2657                              <1> 	; 24/07/2015
  2658                              <1> 	; 20/07/2015
  2659                              <1> 	; 23/06/2015
  2660                              <1> 	; 18/04/2015
  2661                              <1> 	; 12/04/2015
  2662                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2663                              <1> 	;
  2664                              <1> 	; INPUT ->
  2665                              <1> 	;	EAX = physical page address
  2666                              <1> 	;	      (use present value if EAX = 0)
  2667                              <1> 	;	EBX = virtual (linear) address
  2668                              <1> 	;	ECX = page attributes (lower 12 bits)
  2669                              <1> 	;	      (higher 20 bits must be ZERO)
  2670                              <1> 	;	      (bit 0 must be 1)	 
  2671                              <1> 	;	u.pgdir = page directory (physical) address
  2672                              <1> 	; OUTPUT ->
  2673                              <1> 	;	EAX = physical page address
  2674                              <1> 	;	(EDX = PTE value)
  2675                              <1> 	;	EBX = virtual address
  2676                              <1> 	;
  2677                              <1> 	;	CF = 1 -> error
  2678                              <1> 	;
  2679                              <1> 	; Modified Registers -> EAX, EDX
  2680                              <1> 	;
  2681 00002E72 50                  <1> 	push	eax
  2682 00002E73 A1[0C760000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2683 00002E78 E837000000          <1> 	call 	get_pde
  2684                              <1> 		; EDX = PDE address
  2685                              <1> 		; EAX = PDE value
  2686 00002E7D 5A                  <1> 	pop	edx ; physical page address
  2687 00002E7E 722A                <1> 	jc	short spte_err ; PDE not present
  2688                              <1> 	;
  2689 00002E80 53                  <1> 	push	ebx ; 24/07/2015
  2690 00002E81 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2691                              <1> 			    ; EDX = PT address (physical)	
  2692 00002E85 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2693 00002E88 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2694                              <1> 			 ; clear higher 10 bits (PD bits)
  2695 00002E8E C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2696 00002E91 01C3                <1> 	add	ebx, eax
  2697                              <1> 	;
  2698 00002E93 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2699 00002E95 A801                <1> 	test	al, 1
  2700 00002E97 740C                <1> 	jz	short spte_0
  2701 00002E99 09D2                <1> 	or	edx, edx
  2702 00002E9B 750F                <1> 	jnz	short spte_1
  2703 00002E9D 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2704 00002EA1 89C2                <1> 	mov	edx, eax
  2705 00002EA3 EB09                <1> 	jmp	short spte_2	
  2706                              <1> spte_0:
  2707                              <1> 	; If this PTE contains a swap (disk) address,
  2708                              <1> 	; it can be updated by using 'swap_in' procedure
  2709                              <1> 	; only!
  2710 00002EA5 21C0                <1> 	and	eax, eax
  2711 00002EA7 7403                <1> 	jz	short spte_1
  2712                              <1> 	; 24/07/2015
  2713                              <1> 	; swapped page ! (on disk)
  2714 00002EA9 5B                  <1> 	pop	ebx
  2715                              <1> spte_err:
  2716 00002EAA F9                  <1> 	stc
  2717 00002EAB C3                  <1> 	retn
  2718                              <1> spte_1: 
  2719 00002EAC 89D0                <1> 	mov	eax, edx
  2720                              <1> spte_2:
  2721 00002EAE 09CA                <1> 	or	edx, ecx
  2722                              <1> 	; 23/06/2015
  2723 00002EB0 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2724                              <1> 	; 24/07/2015
  2725 00002EB2 5B                  <1> 	pop	ebx
  2726 00002EB3 C3                  <1> 	retn
  2727                              <1> 
  2728                              <1> get_pde:	; Get present value of the relevant PDE
  2729                              <1> 	; 20/07/2015
  2730                              <1> 	; 18/04/2015
  2731                              <1> 	; 12/04/2015
  2732                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2733                              <1> 	;
  2734                              <1> 	; INPUT ->
  2735                              <1> 	;	EBX = virtual (linear) address
  2736                              <1> 	;	EAX = page directory (physical) address
  2737                              <1> 	; OUTPUT ->
  2738                              <1> 	;	EDX = Page directory entry address
  2739                              <1> 	;	EAX = Page directory entry value
  2740                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2741                              <1> 	; Modified Registers -> EDX, EAX
  2742                              <1> 	;
  2743 00002EB4 89DA                <1> 	mov	edx, ebx
  2744 00002EB6 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2745 00002EB9 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2746 00002EBC 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2747 00002EBE 8B02                <1> 	mov	eax, [edx]
  2748 00002EC0 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2749 00002EC2 751F                <1> 	jnz	short gpte_retn
  2750 00002EC4 F9                  <1> 	stc
  2751                              <1> gpde_retn:	
  2752 00002EC5 C3                  <1> 	retn
  2753                              <1> 
  2754                              <1> get_pte:
  2755                              <1> 		; Get present value of the relevant PTE
  2756                              <1> 	; 29/07/2015
  2757                              <1> 	; 20/07/2015
  2758                              <1> 	; 18/04/2015
  2759                              <1> 	; 12/04/2015
  2760                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2761                              <1> 	;
  2762                              <1> 	; INPUT ->
  2763                              <1> 	;	EBX = virtual (linear) address
  2764                              <1> 	;	EAX = page directory (physical) address
  2765                              <1> 	; OUTPUT ->
  2766                              <1> 	;	EDX = Page table entry address (if CF=0)
  2767                              <1> 	;	      Page directory entry address (if CF=1)
  2768                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2769                              <1> 	;	EAX = Page table entry value (page address)
  2770                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2771                              <1> 	; Modified Registers -> EAX, EDX
  2772                              <1> 	;
  2773 00002EC6 E8E9FFFFFF          <1> 	call 	get_pde
  2774 00002ECB 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2775                              <1> 	;jnc	short gpte_1
  2776                              <1> 	;retn
  2777                              <1> ;gpte_1:
  2778 00002ECD 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2779 00002ED1 89DA                <1> 	mov	edx, ebx
  2780 00002ED3 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2781 00002ED6 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2782                              <1> 			 ; clear higher 10 bits (PD bits)
  2783 00002EDC C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2784 00002EDF 01C2                <1> 	add	edx, eax
  2785 00002EE1 8B02                <1> 	mov	eax, [edx]
  2786                              <1> gpte_retn:
  2787 00002EE3 C3                  <1> 	retn
  2788                              <1> 
  2789                              <1> deallocate_page_dir:
  2790                              <1> 	; 15/09/2015
  2791                              <1> 	; 05/08/2015
  2792                              <1> 	; 30/04/2015
  2793                              <1> 	; 28/04/2015
  2794                              <1> 	; 17/10/2014
  2795                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2796                              <1> 	;
  2797                              <1> 	; INPUT ->
  2798                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2799                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2800                              <1> 	; OUTPUT ->
  2801                              <1> 	;	All of page tables in the page directory
  2802                              <1> 	;	and page dir's itself will be deallocated
  2803                              <1> 	;	except 'read only' duplicated pages (will be converted
  2804                              <1> 	;	to writable pages).
  2805                              <1> 	;
  2806                              <1> 	; Modified Registers -> EAX
  2807                              <1> 	;
  2808                              <1> 	;
  2809 00002EE4 56                  <1> 	push	esi
  2810 00002EE5 51                  <1> 	push	ecx
  2811 00002EE6 50                  <1> 	push	eax
  2812 00002EE7 89C6                <1> 	mov	esi, eax 
  2813 00002EE9 31C9                <1> 	xor	ecx, ecx
  2814                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2815                              <1> 	; it must not be deallocated
  2816 00002EEB 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2817                              <1> dapd_0:
  2818 00002EED AD                  <1> 	lodsd
  2819 00002EEE A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2820 00002EF0 7409                <1> 	jz	short dapd_1	
  2821 00002EF2 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2822 00002EF6 E812000000          <1> 	call	deallocate_page_table			
  2823                              <1> dapd_1:
  2824 00002EFB 41                  <1> 	inc	ecx ; page directory entry index
  2825 00002EFC 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2826 00002F02 72E9                <1> 	jb	short dapd_0
  2827                              <1> dapd_2:
  2828 00002F04 58                  <1> 	pop	eax
  2829 00002F05 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2830 00002F0A 59                  <1> 	pop	ecx
  2831 00002F0B 5E                  <1> 	pop	esi
  2832 00002F0C C3                  <1> 	retn
  2833                              <1> 
  2834                              <1> deallocate_page_table:
  2835                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2836                              <1> 	;	 (temporary modifications)
  2837                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2838                              <1> 	; 19/09/2015
  2839                              <1> 	; 15/09/2015
  2840                              <1> 	; 05/08/2015
  2841                              <1> 	; 30/04/2015
  2842                              <1> 	; 28/04/2015
  2843                              <1> 	; 24/10/2014
  2844                              <1> 	; 23/10/2014
  2845                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2846                              <1> 	;
  2847                              <1> 	; INPUT ->
  2848                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2849                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2850                              <1> 	;	(ECX = page directory entry index)
  2851                              <1> 	; OUTPUT ->
  2852                              <1> 	;	All of pages in the page table and page table's itself
  2853                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2854                              <1> 	;	(will be converted to writable pages).
  2855                              <1> 	;
  2856                              <1> 	; Modified Registers -> EAX
  2857                              <1> 	;
  2858 00002F0D 56                  <1> 	push	esi
  2859 00002F0E 57                  <1> 	push	edi
  2860 00002F0F 52                  <1> 	push	edx
  2861 00002F10 50                  <1> 	push	eax ; *
  2862 00002F11 89C6                <1> 	mov	esi, eax 
  2863 00002F13 31FF                <1> 	xor	edi, edi ; 0
  2864                              <1> dapt_0:
  2865 00002F15 AD                  <1> 	lodsd
  2866 00002F16 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2867 00002F18 7455                <1> 	jz	short dapt_1
  2868                              <1> 	;
  2869 00002F1A A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2870                              <1> 				  ; (must be 1)
  2871 00002F1C 753F                <1> 	jnz	short dapt_3
  2872                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2873 00002F1E 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2874                              <1> 				   ; as child's page ?
  2875 00002F22 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2876                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2877                              <1> 	; ECX = page directory entry index (0-1023)
  2878 00002F24 53                  <1> 	push	ebx
  2879 00002F25 51                  <1> 	push	ecx
  2880 00002F26 66C1E102            <1> 	shl	cx, 2 ; *4 
  2881 00002F2A 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2882 00002F2C 8B0B                <1> 	mov	ecx, [ebx]
  2883 00002F2E F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2884 00002F31 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2885 00002F33 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2886                              <1> 	; EDI = page table entry index (0-1023)
  2887 00002F38 89FA                <1> 	mov	edx, edi 
  2888 00002F3A 66C1E202            <1> 	shl	dx, 2 ; *4 
  2889 00002F3E 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2890 00002F40 8B1A                <1> 	mov	ebx, [edx]
  2891 00002F42 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2892 00002F45 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2893 00002F47 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2894 00002F4B 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2895 00002F50 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2896 00002F52 7507                <1> 	jne	short dapt_2	; not same page
  2897                              <1> 				; deallocate the child's page
  2898 00002F54 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2899 00002F57 59                  <1> 	pop	ecx
  2900 00002F58 5B                  <1> 	pop	ebx
  2901 00002F59 EB0D                <1> 	jmp	short dapt_4
  2902                              <1> 
  2903                              <1> ; 17/04/2021
  2904                              <1> ; ('dapt_1' is disabled as temporary)
  2905                              <1> ;
  2906                              <1> ;dapt_1:
  2907                              <1> ;	or	eax, eax	; swapped page ?
  2908                              <1> ;	jz	short dapt_5	; no
  2909                              <1> ;				; yes
  2910                              <1> ;	shr	eax, 1
  2911                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2912                              <1> ;				  ; on the swap disk (or in file)
  2913                              <1> ;	jmp	short dapt_5
  2914                              <1> dapt_2:
  2915 00002F5B 59                  <1> 	pop	ecx
  2916 00002F5C 5B                  <1> 	pop	ebx
  2917                              <1> dapt_3:	
  2918                              <1> 	; 12/07/2016
  2919 00002F5D 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2920 00002F61 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2921                              <1> 	;
  2922                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2923 00002F63 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2924                              <1> dapt_4:
  2925 00002F68 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2926                              <1> dapt_1:	; 17/04/2021 (temporary)
  2927                              <1> dapt_5:
  2928 00002F6F 47                  <1> 	inc	edi ; page table entry index
  2929 00002F70 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2930 00002F76 729D                <1> 	jb	short dapt_0
  2931                              <1> 	;
  2932 00002F78 58                  <1> 	pop	eax ; *
  2933 00002F79 5A                  <1> 	pop	edx
  2934 00002F7A 5F                  <1> 	pop	edi	
  2935 00002F7B 5E                  <1> 	pop	esi
  2936                              <1> 	;
  2937                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2938                              <1> 	;retn
  2939                              <1> 
  2940                              <1> deallocate_page:
  2941                              <1> 	; 15/09/2015
  2942                              <1> 	; 28/04/2015
  2943                              <1> 	; 10/03/2015
  2944                              <1> 	; 17/10/2014
  2945                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2946                              <1> 	;
  2947                              <1> 	; INPUT -> 
  2948                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2949                              <1> 	; OUTPUT ->
  2950                              <1> 	;	[free_pages] is increased
  2951                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2952                              <1> 	;	CF = 1 if the page is already deallocated
  2953                              <1> 	; 	       (or not allocated) before.  
  2954                              <1> 	;
  2955                              <1> 	; Modified Registers -> EAX
  2956                              <1> 	;
  2957 00002F7C 53                  <1> 	push	ebx
  2958 00002F7D 52                  <1> 	push	edx
  2959                              <1> 	;
  2960 00002F7E C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2961                              <1> 				     ; 12 bits right
  2962                              <1> 				     ; to get page number
  2963 00002F81 89C2                <1> 	mov	edx, eax
  2964                              <1> 	; 15/09/2015
  2965 00002F83 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2966                              <1> 				     ; (1 allocation bit = 1 page)
  2967                              <1> 				     ; (1 allocation bytes = 8 pages)
  2968 00002F86 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2969                              <1> 				     ; (to get 32 bit position)			
  2970                              <1> 	;
  2971 00002F89 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2972 00002F8E 01D3                <1> 	add	ebx, edx
  2973 00002F90 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2974                              <1> 				     ; (allocation bit position)	 
  2975 00002F93 3B15[A4700000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2976                              <1> 				     ; than the address in 'next_page' ?
  2977                              <1> 				     ; (next/first free page value)		
  2978 00002F99 7306                <1> 	jnb	short dap_1	     ; no	
  2979 00002F9B 8915[A4700000]      <1> 	mov	[next_page], edx     ; yes
  2980                              <1> dap_1:
  2981 00002FA1 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2982                              <1> 				     ; set relevant bit to 1.
  2983                              <1> 				     ; set CF to the previous bit value	
  2984                              <1> 	;cmc			     ; complement carry flag	
  2985                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2986                              <1> 				     ; if the page is already deallocated
  2987                              <1> 				     ; before.	
  2988 00002FA4 FF05[A0700000]      <1>         inc     dword [free_pages]
  2989                              <1> dap_2:
  2990 00002FAA 5A                  <1> 	pop	edx
  2991 00002FAB 5B                  <1> 	pop	ebx
  2992 00002FAC C3                  <1> 	retn
  2993                              <1> 
  2994                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2995                              <1> ;;                                                              ;;
  2996                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2997                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2998                              <1> ;;                                                              ;;
  2999                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3000                              <1> 
  3001                              <1> ;;$Revision: 5057 $
  3002                              <1> 
  3003                              <1> 
  3004                              <1> ;;align 4
  3005                              <1> ;;proc alloc_page
  3006                              <1> 
  3007                              <1> ;;        pushfd
  3008                              <1> ;;        cli
  3009                              <1> ;;        push    ebx
  3010                              <1> ;;;//-
  3011                              <1> ;;        cmp     [pg_data.pages_free], 1
  3012                              <1> ;;        jle     .out_of_memory
  3013                              <1> ;;;//-
  3014                              <1> ;;
  3015                              <1> ;;        mov     ebx, [page_start]
  3016                              <1> ;;        mov     ecx, [page_end]
  3017                              <1> ;;.l1:
  3018                              <1> ;;        bsf     eax, [ebx];
  3019                              <1> ;;        jnz     .found
  3020                              <1> ;;        add     ebx, 4
  3021                              <1> ;;        cmp     ebx, ecx
  3022                              <1> ;;        jb      .l1
  3023                              <1> ;;        pop     ebx
  3024                              <1> ;;        popfd
  3025                              <1> ;;        xor     eax, eax
  3026                              <1> ;;        ret
  3027                              <1> ;;.found:
  3028                              <1> ;;;//-
  3029                              <1> ;;        dec     [pg_data.pages_free]
  3030                              <1> ;;        jz      .out_of_memory
  3031                              <1> ;;;//-
  3032                              <1> ;;        btr     [ebx], eax
  3033                              <1> ;;        mov     [page_start], ebx
  3034                              <1> ;;        sub     ebx, sys_pgmap
  3035                              <1> ;;        lea     eax, [eax+ebx*8]
  3036                              <1> ;;        shl     eax, 12
  3037                              <1> ;;;//-       dec [pg_data.pages_free]
  3038                              <1> ;;        pop     ebx
  3039                              <1> ;;        popfd
  3040                              <1> ;;        ret
  3041                              <1> ;;;//-
  3042                              <1> ;;.out_of_memory:
  3043                              <1> ;;        mov     [pg_data.pages_free], 1
  3044                              <1> ;;        xor     eax, eax
  3045                              <1> ;;        pop     ebx
  3046                              <1> ;;        popfd
  3047                              <1> ;;        ret
  3048                              <1> ;;;//-
  3049                              <1> ;;endp
  3050                              <1> 
  3051                              <1> duplicate_page_dir:
  3052                              <1> 	; 21/09/2015
  3053                              <1> 	; 31/08/2015
  3054                              <1> 	; 20/07/2015
  3055                              <1> 	; 28/04/2015
  3056                              <1> 	; 27/04/2015
  3057                              <1> 	; 18/04/2015
  3058                              <1> 	; 12/04/2015
  3059                              <1> 	; 18/10/2014
  3060                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3061                              <1> 	;
  3062                              <1> 	; INPUT -> 
  3063                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3064                              <1> 	;		    page directory.
  3065                              <1> 	; OUTPUT ->
  3066                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3067                              <1> 	;	       page directory.
  3068                              <1> 	;	(New page directory with new page table entries.)
  3069                              <1> 	;	(New page tables with read only copies of the parent's
  3070                              <1> 	;	pages.)
  3071                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3072                              <1> 	;
  3073                              <1> 	; Modified Registers -> none (except EAX)
  3074                              <1> 	;
  3075 00002FAD E802FEFFFF          <1> 	call	allocate_page
  3076 00002FB2 723E                <1> 	jc	short dpd_err
  3077                              <1> 	;
  3078 00002FB4 55                  <1> 	push	ebp ; 20/07/2015
  3079 00002FB5 56                  <1> 	push	esi
  3080 00002FB6 57                  <1> 	push	edi
  3081 00002FB7 53                  <1> 	push	ebx
  3082 00002FB8 51                  <1> 	push	ecx
  3083 00002FB9 8B35[0C760000]      <1> 	mov	esi, [u.pgdir]
  3084 00002FBF 89C7                <1> 	mov	edi, eax
  3085 00002FC1 50                  <1> 	push	eax ; save child's page directory address
  3086                              <1> 	; 31/08/2015
  3087                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3088                              <1> 	; (use same system space for all user page tables) 
  3089 00002FC2 A5                  <1> 	movsd
  3090 00002FC3 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3091 00002FC8 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3092                              <1> dpd_0:	
  3093 00002FCD AD                  <1> 	lodsd
  3094                              <1> 	;or	eax, eax
  3095                              <1>         ;jnz     short dpd_1
  3096 00002FCE A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3097 00002FD0 7508                <1> 	jnz	short dpd_1
  3098                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3099 00002FD2 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3100 00002FD8 EB0F                <1> 	jmp	short dpd_2
  3101                              <1> dpd_1:	
  3102 00002FDA 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3103 00002FDE 89C3                <1> 	mov	ebx, eax
  3104                              <1> 	; EBX = Parent's page table address
  3105 00002FE0 E81F000000          <1> 	call	duplicate_page_table
  3106 00002FE5 720C                <1> 	jc	short dpd_p_err
  3107                              <1> 	; EAX = Child's page table address
  3108 00002FE7 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3109                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3110                              <1> 			 ; (present, writable, user)
  3111                              <1> dpd_2:
  3112 00002FE9 AB                  <1> 	stosd
  3113 00002FEA E2E1                <1> 	loop	dpd_0
  3114                              <1> 	;
  3115 00002FEC 58                  <1> 	pop	eax  ; restore child's page directory address
  3116                              <1> dpd_3:
  3117 00002FED 59                  <1> 	pop	ecx
  3118 00002FEE 5B                  <1> 	pop	ebx
  3119 00002FEF 5F                  <1> 	pop	edi
  3120 00002FF0 5E                  <1> 	pop	esi
  3121 00002FF1 5D                  <1> 	pop	ebp ; 20/07/2015
  3122                              <1> dpd_err:
  3123 00002FF2 C3                  <1> 	retn
  3124                              <1> dpd_p_err:
  3125                              <1> 	; release the allocated pages missing (recover free space)
  3126 00002FF3 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3127 00002FF4 8B1D[0C760000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3128 00002FFA E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3129 00002FFF 29C0                <1> 	sub	eax, eax ; 0
  3130 00003001 F9                  <1> 	stc
  3131 00003002 EBE9                <1> 	jmp	short dpd_3	
  3132                              <1> 
  3133                              <1> duplicate_page_table:
  3134                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3135                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3136                              <1> 	;	 (temporary modifications)
  3137                              <1> 	; 16/04/2021 (Retro UNIX 386 v2)
  3138                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3139                              <1> 	; 21/09/2015
  3140                              <1> 	; 20/07/2015
  3141                              <1> 	; 05/05/2015
  3142                              <1> 	; 28/04/2015
  3143                              <1> 	; 27/04/2015
  3144                              <1> 	; 18/04/2015
  3145                              <1> 	; 18/10/2014
  3146                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3147                              <1> 	;
  3148                              <1> 	; INPUT -> 
  3149                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3150                              <1> 	;       20/02/2017		 
  3151                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3152                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3153                              <1> 	; OUTPUT ->
  3154                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3155                              <1> 	;	      (with 'read only' attribute of page table entries)
  3156                              <1> 	;	20/02/2017
  3157                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3158                              <1> 	;	
  3159                              <1> 	;	CF = 1 -> error 
  3160                              <1> 	;
  3161                              <1> 	; Modified Registers -> EBP (except EAX)
  3162                              <1> 	;
  3163 00003004 E8ABFDFFFF          <1> 	call	allocate_page
  3164 00003009 725B                <1> 	jc	short dpt_err
  3165                              <1> 	;
  3166 0000300B 50                  <1> 	push	eax ; *
  3167 0000300C 56                  <1> 	push	esi
  3168 0000300D 57                  <1> 	push	edi
  3169 0000300E 52                  <1> 	push	edx
  3170 0000300F 51                  <1> 	push	ecx
  3171                              <1> 	;
  3172 00003010 89DE                <1> 	mov	esi, ebx
  3173 00003012 89C7                <1> 	mov	edi, eax
  3174 00003014 89C2                <1> 	mov	edx, eax
  3175 00003016 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3176                              <1> dpt_0:
  3177 0000301C AD                  <1> 	lodsd
  3178 0000301D 21C0                <1> 	and	eax, eax
  3179 0000301F 7435                <1> 	jz	short dpt_3
  3180 00003021 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3181                              <1> 	; 17/04/2021 (temporary)
  3182 00003023 7503                <1> 	jnz	short dpt_1
  3183                              <1> 	;jz	short dpt_p_err
  3184                              <1> 	; 31/12/2021
  3185 00003025 F9                  <1> 	stc
  3186 00003026 EB39                <1> 	jmp	short dpt_p_err
  3187                              <1> 
  3188                              <1> ; 17/04/2021
  3189                              <1> ; ('reload_page' procedure call is disabled as temporary)
  3190                              <1> ;
  3191                              <1> ;	; 20/07/2015
  3192                              <1> ;	; ebp = virtual (linear) address of the memory page
  3193                              <1> ;	call	reload_page ; 28/04/2015
  3194                              <1> ;	jc	short dpt_p_err
  3195                              <1> dpt_1:
  3196                              <1> 	; 21/09/2015
  3197 00003028 89C1                <1> 	mov	ecx, eax
  3198 0000302A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3199 0000302E F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3200 00003031 751A                <1> 	jnz	short dpt_2
  3201                              <1> 	; Read only (parent) page
  3202                              <1> 	; 	- there is a third process which uses this page -
  3203                              <1> 	; Allocate a new page for the child process
  3204 00003033 E87CFDFFFF          <1> 	call	allocate_page
  3205 00003038 7227                <1> 	jc	short dpt_p_err
  3206 0000303A 57                  <1> 	push	edi
  3207 0000303B 56                  <1> 	push	esi
  3208 0000303C 89CE                <1> 	mov	esi, ecx
  3209 0000303E 89C7                <1> 	mov	edi, eax
  3210 00003040 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3211 00003045 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3212 00003047 5E                  <1> 	pop	esi
  3213 00003048 5F                  <1> 	pop	edi
  3214                              <1> 	;
  3215                              <1> 
  3216                              <1> ; 17/04/2021
  3217                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  3218                              <1> ; 
  3219                              <1> ;	push	ebx
  3220                              <1> ;	push	eax
  3221                              <1> ;	; 20/07/2015
  3222                              <1> ;	mov	ebx, ebp
  3223                              <1> ;	; ebx = virtual (linear) address of the memory page
  3224                              <1> ;	call	add_to_swap_queue
  3225                              <1> ;	pop	eax
  3226                              <1> ;	pop	ebx
  3227                              <1> 
  3228                              <1> 	; 21/09/2015
  3229 00003049 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3230                              <1> 		; user + writable + present page
  3231 0000304B EB09                <1> 	jmp	short dpt_3
  3232                              <1> dpt_2:
  3233                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3234 0000304D 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3235                              <1> 		    ; (read only page!)
  3236 0000304F 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3237 00003052 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3238                              <1> dpt_3:
  3239 00003056 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3240                              <1> 	;
  3241 00003057 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3242                              <1> 	;
  3243 0000305D 39D7                <1> 	cmp	edi, edx
  3244 0000305F 72BB                <1> 	jb	short dpt_0
  3245                              <1> dpt_p_err:
  3246 00003061 59                  <1> 	pop	ecx
  3247 00003062 5A                  <1> 	pop	edx
  3248 00003063 5F                  <1> 	pop	edi
  3249 00003064 5E                  <1> 	pop	esi
  3250 00003065 58                  <1> 	pop	eax ; *
  3251                              <1> dpt_err:
  3252 00003066 C3                  <1> 	retn
  3253                              <1> 
  3254                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3255                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3256                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3257                              <1> 	;	 (temporary modifications)
  3258                              <1> 	; 21/09/2015
  3259                              <1> 	; 19/09/2015
  3260                              <1> 	; 17/09/2015
  3261                              <1> 	; 28/08/2015
  3262                              <1> 	; 20/07/2015
  3263                              <1> 	; 28/06/2015
  3264                              <1> 	; 03/05/2015
  3265                              <1> 	; 30/04/2015
  3266                              <1> 	; 18/04/2015
  3267                              <1> 	; 12/04/2015
  3268                              <1> 	; 30/10/2014
  3269                              <1> 	; 11/09/2014
  3270                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3271                              <1> 	;
  3272                              <1> 	; Note: This is not an interrupt/exception handler.
  3273                              <1> 	;	This is a 'page fault remedy' subroutine 
  3274                              <1> 	;	which will be called by standard/uniform
  3275                              <1> 	;	exception handler.
  3276                              <1> 	;
  3277                              <1> 	; INPUT -> 
  3278                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3279                              <1> 	;
  3280                              <1> 	;	cr2 = the virtual (linear) address 
  3281                              <1> 	;	      which has caused to page fault (19/09/2015)
  3282                              <1> 	;
  3283                              <1> 	; OUTPUT ->
  3284                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3285                              <1> 	;	EAX = 0 -> no error
  3286                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3287                              <1> 	;
  3288                              <1> 	; Modified Registers -> none (except EAX)
  3289                              <1> 	;	
  3290                              <1>         ;
  3291                              <1>         ; ERROR CODE:
  3292                              <1> 	;	 31  .....	4   3	2   1	0
  3293                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3294                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3295                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3296                              <1> 	;
  3297                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3298                              <1>     	;		a page-protection violation. When not set,
  3299                              <1> 	;		it was caused by a non-present page.
  3300                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3301                              <1> 	;		a page write. When not set, it was caused
  3302                              <1> 	;		by a page read.
  3303                              <1> 	; U : USER    -	When set, the page fault was caused 
  3304                              <1> 	;		while CPL = 3. 
  3305                              <1> 	;		This does not necessarily mean that
  3306                              <1> 	;		the page fault was a privilege violation.
  3307                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3308                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3309                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3310                              <1> 	;     FETCH	an instruction fetch
  3311                              <1> 	;
  3312                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3313                              <1> 	;  31               22                  12 11                    0
  3314                              <1> 	; +-------------------+-------------------+-----------------------+
  3315                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3316                              <1>        	; +-------------------+-------------------+-----------------------+
  3317                              <1> 	;
  3318                              <1> 
  3319                              <1> 	;; CR3 REGISTER (Control Register 3)
  3320                              <1> 	;  31                                   12             5 4 3 2   0
  3321                              <1> 	; +---------------------------------------+-------------+---+-----+
  3322                              <1>       	; |                                       |  		|P|P|     |
  3323                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3324                              <1>       	; |                                       | 		|D|T|     |
  3325                              <1>    	; +---------------------------------------+-------------+---+-----+
  3326                              <1> 	;
  3327                              <1> 	;	PWT    - WRITE THROUGH
  3328                              <1> 	;	PCD    - CACHE DISABLE		
  3329                              <1> 	;
  3330                              <1> 	;
  3331                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3332                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3333                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3334                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3335                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3336                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3337                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3338                              <1> 	;
  3339                              <1>         ;       P      - PRESENT
  3340                              <1>         ;       R/W    - READ/WRITE
  3341                              <1>         ;       U/S    - USER/SUPERVISOR
  3342                              <1> 	;	PWT    - WRITE THROUGH
  3343                              <1> 	;	PCD    - CACHE DISABLE	
  3344                              <1> 	;	A      - ACCESSED	
  3345                              <1>         ;       D      - DIRTY (IGNORED)
  3346                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3347                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3348                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3349                              <1> 	;
  3350                              <1> 	;
  3351                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3352                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3353                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3354                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3355                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3356                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3357                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3358                              <1> 	;
  3359                              <1>         ;       P      - PRESENT
  3360                              <1>         ;       R/W    - READ/WRITE
  3361                              <1>         ;       U/S    - USER/SUPERVISOR
  3362                              <1> 	;	PWT    - WRITE THROUGH
  3363                              <1> 	;	PCD    - CACHE DISABLE	
  3364                              <1> 	;	A      - ACCESSED	
  3365                              <1>         ;       D      - DIRTY
  3366                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3367                              <1> 	;	G      - GLOBAL	 
  3368                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3369                              <1> 	;
  3370                              <1> 	;
  3371                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3372                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3373                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3374                              <1>       	; |                                       |     | | | | | | |U|R| |
  3375                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3376                              <1>       	; |                                       |     | | | | | | |S|W| |
  3377                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3378                              <1> 	;
  3379                              <1>         ;       P      - PRESENT
  3380                              <1>         ;       R/W    - READ/WRITE
  3381                              <1>         ;       U/S    - USER/SUPERVISOR
  3382                              <1>         ;       D      - DIRTY
  3383                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3384                              <1> 	;
  3385                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3386                              <1> 	;
  3387                              <1> 	;
  3388                              <1> 	;; Invalid Page Table Entry
  3389                              <1> 	; 31                                                           1 0
  3390                              <1>       	; +-------------------------------------------------------------+-+
  3391                              <1>       	; |                                                             | |
  3392                              <1>       	; |                          AVAILABLE                          |0|
  3393                              <1>       	; |                                                             | |
  3394                              <1>       	; +-------------------------------------------------------------+-+
  3395                              <1> 	;
  3396                              <1> 
  3397 00003067 53                  <1> 	push	ebx
  3398 00003068 52                  <1> 	push	edx
  3399 00003069 51                  <1> 	push	ecx
  3400                              <1> 	;
  3401                              <1> 	; 21/09/2015 (debugging)
  3402 0000306A FF05[24760000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3403 00003070 FF05[50710000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3404                              <1> 	; 28/06/2015
  3405                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3406 00003076 8A15[48710000]      <1> 	mov	dl, [error_code]
  3407                              <1> 	;
  3408 0000307C F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3409                              <1> 			; sign
  3410 0000307F 7416                <1> 	jz	short pfh_alloc_np
  3411                              <1> 	; 
  3412                              <1> 	; If it is not a 'write on read only page' type page fault
  3413                              <1> 	; major page fault error with minor reason must be returned without 
  3414                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3415                              <1> 	; after return here!
  3416                              <1> 	; Page fault will be remedied, by copying page contents
  3417                              <1> 	; to newly allocated page with write permission;
  3418                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3419                              <1> 	; used for working with minimum possible memory usage. 
  3420                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3421                              <1> 	; process with 'read only' flag. If the child process attempts to
  3422                              <1> 	; write on these read only pages, page fault will be directed here
  3423                              <1> 	; for allocating a new page with same data/content. 
  3424                              <1> 	;
  3425                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3426                              <1> 	; will not force to separate CODE and DATA space 
  3427                              <1> 	; in a process/program... 
  3428                              <1> 	; CODE segment/section may contain DATA!
  3429                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3430                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3431                              <1> 	;	
  3432 00003081 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3433                              <1> 			; sign
  3434 00003084 744F                <1>         jz	short pfh_p_err
  3435                              <1> 	; 31/08/2015
  3436 00003086 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3437                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3438 00003089 744A                <1>         jz	short pfh_pv_err
  3439                              <1> 	;
  3440                              <1> 	; make a new page and copy the parent's page content
  3441                              <1> 	; as the child's new page content
  3442                              <1> 	;
  3443 0000308B 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3444                              <1> 			 ; which has caused to page fault
  3445 0000308E E87C000000          <1> 	call 	copy_page
  3446 00003093 7239                <1>         jc	short pfh_im_err ; insufficient memory
  3447                              <1> 	;
  3448 00003095 EB72                <1>         jmp     pfh_cpp_ok
  3449                              <1> 	;
  3450                              <1> pfh_alloc_np:
  3451 00003097 E818FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3452 0000309C 7230                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3453                              <1> pfh_chk_cpl:
  3454                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3455                              <1> 		; (Lower 12 bits are ZERO, because 
  3456                              <1> 		;	the address is on a page boundary)
  3457 0000309E 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3458 000030A1 7505                <1> 	jnz	short pfh_um
  3459                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3460 000030A3 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3461                              <1> 			 ; of the current/active page directory
  3462                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3463                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3464 000030A6 EB06                <1> 	jmp	short pfh_get_pde
  3465                              <1> 	;
  3466                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3467 000030A8 8B1D[0C760000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3468                              <1> 			; Physical address of the USER's page directory
  3469                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3470                              <1> pfh_get_pde:
  3471 000030AE 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3472 000030B1 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3473                              <1> 			 ; which has been caused to page fault
  3474                              <1> 			 ;
  3475 000030B4 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3476 000030B7 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3477                              <1> 	;
  3478 000030BA 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3479 000030BC 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3480 000030BE F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3481 000030C1 741A                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3482                              <1> 			  	  ; set/validate page directory entry
  3483 000030C3 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3484 000030C8 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3485 000030CA 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3486 000030CC EB25                <1> 	jmp	short pfh_get_pte
  3487                              <1> 
  3488                              <1> 	; 31/12/2021 (short jump)
  3489                              <1> pfh_im_err:
  3490 000030CE B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3491                              <1> 			; Major (Primary) Error: Page Fault
  3492                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3493 000030D3 EB36                <1> 	jmp	short pfh_err_retn
  3494                              <1> 
  3495                              <1> 	; 31/12/2021
  3496                              <1> pfh_p_err: ; 09/03/2015
  3497                              <1> pfh_pv_err:
  3498                              <1> 	; Page fault was caused by a protection-violation
  3499 000030D5 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3500                              <1> 			; Major (Primary) Error: Page Fault
  3501                              <1> 			; Minor (Secondary) Error: Protection violation !
  3502 000030DA F9                  <1> 	stc
  3503 000030DB EB2E                <1> 	jmp	short pfh_err_retn
  3504                              <1> 
  3505                              <1> pfh_set_pde:
  3506                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3507                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3508                              <1> 	;
  3509 000030DD 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3510 000030DF 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3511 000030E1 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3512 000030E3 89C3                <1> 	mov	ebx, eax
  3513 000030E5 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3514 000030EA 72E2                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3515                              <1> pfh_spde_1:
  3516                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3517 000030EC 89C1                <1> 	mov	ecx, eax
  3518 000030EE E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3519                              <1> pfh_get_pte:
  3520 000030F3 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3521                              <1> 			 ; which has been caused to page fault
  3522 000030F6 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3523 000030F8 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3524                              <1> 			 ; higher 20 bits of the page fault address 
  3525 000030FB 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3526 00003100 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3527 00003103 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3528                              <1> ; 17/04/2021 temporary
  3529                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3530                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3531                              <1> ; 17/04/2021
  3532                              <1> ; ('swap_in' procedure call has been disabled as temporary)
  3533                              <1> ;
  3534                              <1> ;	and	eax, eax
  3535                              <1> ;	jz	short pfh_gpte_1
  3536                              <1> ;	; 20/07/2015
  3537                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3538                              <1> ;	push	ebp ; 20/07/2015
  3539                              <1> ;	mov	ebp, cr2
  3540                              <1> ;		; ECX = physical address of the page table entry
  3541                              <1> ;		; EBX = Memory page address (physical!)
  3542                              <1> ;		; EAX = Swap disk (offset) address
  3543                              <1> ;		; EBP = virtual address (page fault address)
  3544                              <1> ;	call	swap_in
  3545                              <1> ;	pop	ebp
  3546                              <1> ;	jc      short pfh_err_retn
  3547                              <1> ;	xchg	ecx, ebx
  3548                              <1> ;		; EBX = physical address of the page table entry
  3549                              <1> ;		; ECX = new page
  3550                              <1> pfh_gpte_1:
  3551 00003105 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3552 00003107 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3553                              <1> pfh_cpp_ok:
  3554                              <1> ; 17/04/2021
  3555                              <1> ; ('add_to_swap_queue' procedure call has been disabled as temporary)
  3556                              <1> ;
  3557                              <1> ;	; 20/07/2015
  3558                              <1> ;	mov	ebx, cr2
  3559                              <1> ;	call 	add_to_swap_queue
  3560                              <1> 	;
  3561                              <1> 	; The new PTE (which contains the new page) will be added to 
  3562                              <1> 	; the swap queue, here. 
  3563                              <1> 	; (Later, if memory will become insufficient, 
  3564                              <1> 	; one page will be swapped out which is at the head of 
  3565                              <1> 	; the swap queue by using FIFO and access check methods.)
  3566                              <1> 	;
  3567 00003109 31C0                <1> 	xor	eax, eax  ; 0
  3568                              <1> 	;
  3569                              <1> pfh_err_retn:
  3570 0000310B 59                  <1> 	pop	ecx
  3571 0000310C 5A                  <1> 	pop	edx
  3572 0000310D 5B                  <1> 	pop	ebx
  3573 0000310E C3                  <1> 	retn 
  3574                              <1> 	
  3575                              <1> copy_page:
  3576                              <1> 	; 16/04/2021
  3577                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3578                              <1> 	; 22/09/2015
  3579                              <1> 	; 21/09/2015
  3580                              <1> 	; 19/09/2015
  3581                              <1> 	; 07/09/2015
  3582                              <1> 	; 31/08/2015
  3583                              <1> 	; 20/07/2015
  3584                              <1> 	; 05/05/2015
  3585                              <1> 	; 03/05/2015
  3586                              <1> 	; 18/04/2015
  3587                              <1> 	; 12/04/2015
  3588                              <1> 	; 30/10/2014
  3589                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3590                              <1> 	;
  3591                              <1> 	; INPUT -> 
  3592                              <1> 	;	EBX = Virtual (linear) address of source page
  3593                              <1> 	;	     (Page fault address)
  3594                              <1> 	; OUTPUT ->
  3595                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3596                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3597                              <1> 	;	EAX = 0 (CF = 1) 
  3598                              <1> 	;		if there is not a free page to be allocated
  3599                              <1> 	;	(page content of the source page will be copied
  3600                              <1> 	;	onto the target/new page) 	
  3601                              <1> 	;
  3602                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3603                              <1> 	;
  3604                              <1> 
  3605                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3606                              <1> 	; INPUT: 
  3607                              <1> 	;	EBX = Virtual (linear) address of source page
  3608                              <1> 	;	     (Page fault address)
  3609                              <1> 	; OUTPUT:
  3610                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3611                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3612                              <1> 	;	EAX = 0 (CF = 1) 
  3613                              <1> 	;		if there is not a free page to be allocated
  3614                              <1> 	;	(page content of the source page will be copied
  3615                              <1> 	;	onto the target/new page) 	
  3616                              <1> 	;
  3617                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3618                              <1> 	
  3619 0000310F 56                  <1> 	push	esi ; *
  3620 00003110 57                  <1> 	push	edi ; **
  3621                              <1> 	; 16/04/2021
  3622                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3623                              <1> 	;push	ebx ; ***
  3624                              <1> 	;push	ecx ; ****
  3625 00003111 31F6                <1> 	xor 	esi, esi
  3626 00003113 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3627 00003116 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3628 00003118 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3629 0000311B 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3630 0000311E 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3631 00003120 031D[0C760000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3632 00003126 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3633 00003128 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3634 0000312C 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3635 0000312E 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3636 00003134 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3637 00003138 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3638                              <1> 	; 07/09/2015
  3639 0000313A 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3640                              <1> 				     ; read only page as a child process?)	
  3641 0000313F 7509                <1> 	jnz	short cpp_0 ; yes
  3642 00003141 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3643 00003143 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3644 00003148 EB32                <1> 	jmp	short cpp_1
  3645                              <1> cpp_0:
  3646 0000314A 89FE                <1> 	mov	esi, edi
  3647 0000314C 0335[10760000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3648 00003152 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3649 00003154 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3650 00003158 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3651 0000315A 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3652 00003160 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3653 00003164 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3654 00003166 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3655                              <1> 	; 21/09/2015
  3656 00003168 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3657 0000316A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3658                              <1> 	;
  3659 0000316E F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3660 00003171 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3661                              <1> 	;
  3662 00003173 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3663 00003178 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3664 0000317A 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3665                              <1> 			    ; Convert child's page to writable page
  3666                              <1> cpp_1:
  3667 0000317C E833FCFFFF          <1> 	call	allocate_page
  3668 00003181 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3669 00003183 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3670 00003185 7405                <1> 	jz	short cpp_2
  3671                              <1> 		; Convert read only page to writable page 
  3672                              <1> 		;(for the parent of the current process)
  3673                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3674                              <1> 	; 22/09/2015
  3675 00003187 890E                <1> 	mov	[esi], ecx
  3676 00003189 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3677                              <1> 				 ; 1+2+4 = 7
  3678                              <1> cpp_2:
  3679 0000318C 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3680                              <1> 	; 07/09/2015
  3681 0000318E 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3682 00003190 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3683 00003195 F3A5                <1> 	rep	movsd ; 31/08/2015
  3684                              <1> cpp_3:		
  3685 00003197 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3686 00003199 8903                <1> 	mov	[ebx], eax ; Update PTE
  3687 0000319B 28C0                <1> 	sub	al, al ; clear attributes
  3688                              <1> cpp_4:
  3689                              <1> 	; 16/04/2021
  3690                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3691                              <1> 	;pop	ecx ; ****
  3692                              <1> 	;pop	ebx ; ***
  3693 0000319D 5F                  <1> 	pop	edi ; **
  3694 0000319E 5E                  <1> 	pop	esi ; *
  3695 0000319F C3                  <1> 	retn
  3696                              <1> 
  3697                              <1> ;; 28/04/2015
  3698                              <1> ;; 24/10/2014
  3699                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3700                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3701                              <1> ;;
  3702                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3703                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3704                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3705                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3706                              <1> ;;
  3707                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3708                              <1> ;;
  3709                              <1> ;; Method:
  3710                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3711                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3712                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3713                              <1> ;;	When a new page is being allocated, swap queue is updated
  3714                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3715                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3716                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3717                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3718                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3719                              <1> ;;	offset value becomes it's previous offset value - 4.
  3720                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3721                              <1> ;;	the queue/list is not shifted.
  3722                              <1> ;;	After the queue/list shift, newly allocated page is added
  3723                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3724                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3725                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3726                              <1> ;;	
  3727                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3728                              <1> ;;	the first non-accessed, writable page in the list, 
  3729                              <1> ;;	from the head to the tail. The list is shifted to left 
  3730                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3731                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3732                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3733                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3734                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3735                              <1> ;;	procedure will be failed)...
  3736                              <1> ;;
  3737                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3738                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3739                              <1> ;;	(PTE) will be added to the tail of the queue after
  3740                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3741                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3742                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3743                              <1> ;;
  3744                              <1> ;;
  3745                              <1> ;;	
  3746                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3747                              <1> ;;
  3748                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3749                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3750                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3751                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3752                              <1> ;;
  3753                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3754                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3755                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3756                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3757                              <1> ;; 		 (entire swap space must be accessed by using
  3758                              <1> ;;		 31 bit offset address) 
  3759                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3760                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3761                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3762                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3763                              <1> ;;
  3764                              <1> ;; 					
  3765                              <1> ;; Method:
  3766                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3767                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3768                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3769                              <1> ;;	Swapping out is performed by using swap page queue.
  3770                              <1> ;;
  3771                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3772                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3773                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3774                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3775                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3776                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3777                              <1> ;;	calculated by adding offset value to the swap partition's 
  3778                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3779                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3780                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3781                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3782                              <1> ;;	is in a partitioned virtual hard disk.) 
  3783                              <1> ;;
  3784                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3785                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3786                              <1> ;;
  3787                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3788                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3789                              <1> ;;
  3790                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3791                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3792                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3793                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3794                              <1> ;;	it means relevant (respective) block is in use, and, 
  3795                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3796                              <1> ;;      swap disk/file block is free.
  3797                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3798                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3799                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3800                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3801                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3802                              <1> ;;	------------------------------------------------------------
  3803                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3804                              <1> ;;	------------------------------------------------------------
  3805                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3806                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3807                              <1> ;;
  3808                              <1> ;;	..............................................................
  3809                              <1> ;;
  3810                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3811                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3812                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3813                              <1> ;;	position with value of 1 on the table is converted to swap
  3814                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3815                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3816                              <1> ;;	number of physical swap disk or virtual swap disk)
  3817                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3818                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3819                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3820                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3821                              <1> ;;	If disk write procedure returns with error or free count of 
  3822                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3823                              <1> ;;	'insufficient memory error' (cf=1). 
  3824                              <1> ;;
  3825                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3826                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3827                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3828                              <1> ;;	free blocks after a disk write error. It will return to 
  3829                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3830                              <1> ;;
  3831                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3832                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3833                              <1> ;;	address (cf=0). 
  3834                              <1> ;;
  3835                              <1> ;;	..............................................................
  3836                              <1> ;;
  3837                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3838                              <1> ;;	file sectors at specified memory page. Then page allocation
  3839                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3840                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3841                              <1> ;;	to do, except to terminate the process which is the owner of
  3842                              <1> ;;	the swapped page.
  3843                              <1> ;;
  3844                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3845                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3846                              <1> ;;	updates [swpd_first] pointer if it is required.
  3847                              <1> ;;
  3848                              <1> ;;	..............................................................	 
  3849                              <1> ;;
  3850                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3851                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3852                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3853                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3854                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3855                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3856                              <1> ;;
  3857                              <1> 
  3858                              <1> ; 17/04/2021
  3859                              <1> ; ('swap_in' procedure call is disabled as temporary)
  3860                              <1> 
  3861                              <1> ; 30/11/2021 - temporary !
  3862                              <1> ;swap_in:
  3863                              <1> 	; 31/08/2015
  3864                              <1> 	; 20/07/2015
  3865                              <1> 	; 28/04/2015
  3866                              <1> 	; 18/04/2015
  3867                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3868                              <1> 	;
  3869                              <1> 	; INPUT -> 
  3870                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3871                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3872                              <1> 	;	EAX = Offset Address for the swapped page on the
  3873                              <1> 	;	      swap disk or in the swap file.
  3874                              <1> 	;
  3875                              <1> 	; OUTPUT ->
  3876                              <1> 	;	EAX = 0 if loading at memory has been successful
  3877                              <1> 	;
  3878                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3879                              <1> 	;		  or sector not present or drive not ready
  3880                              <1> 	;	     EAX = Error code
  3881                              <1> 	;	     [u.error] = EAX 
  3882                              <1> 	;		       = The last error code for the process
  3883                              <1> 	;		         (will be reset after returning to user)	  
  3884                              <1> 	;
  3885                              <1> 	; Modified Registers -> EAX
  3886                              <1> 	;
  3887                              <1> 
  3888                              <1> ;       cmp     dword [swp_drv], 0
  3889                              <1> ;	jna	short swpin_dnp_err
  3890                              <1> ;
  3891                              <1> ;	cmp	eax, [swpd_size]
  3892                              <1> ;	jnb	short swpin_snp_err
  3893                              <1> ;
  3894                              <1> ;	push	esi
  3895                              <1> ;	push	ebx
  3896                              <1> ;	push	ecx
  3897                              <1> ;	mov	esi, [swp_drv]	
  3898                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3899                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3900                              <1> ;		; size different than 512 bytes, logical disk sector
  3901                              <1> ;		; size is 512 bytes and disk reading procedure
  3902                              <1> ;		; will be performed for reading 4096 bytes
  3903                              <1> ;		; (2*2048, 8*512). 
  3904                              <1> ;	; ESI = Logical disk description table address
  3905                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3906                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3907                              <1> ;	; ECX = Sector count ; 8 sectors
  3908                              <1> ;	push	eax
  3909                              <1> ;	call	logical_disk_read
  3910                              <1> ;	pop	eax
  3911                              <1> ;	jnc	short swpin_read_ok
  3912                              <1> ;	;
  3913                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3914                              <1> ;	mov	[u.error], eax
  3915                              <1> ;	jmp	short swpin_retn
  3916                              <1> ;	;
  3917                              <1> ;swpin_read_ok:
  3918                              <1> ;	; EAX = Offset address (logical sector number)
  3919                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3920                              <1> ;	;
  3921                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3922                              <1> ;	; 20/07/2015
  3923                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3924                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3925                              <1> ;	mov	bl, [u.uno] ; current process number
  3926                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3927                              <1> ;	call	swap_queue_shift
  3928                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3929                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3930                              <1> ;	; zf = 1
  3931                              <1> ;swpin_retn:
  3932                              <1> ;	pop	ecx
  3933                              <1> ;	pop	ebx
  3934                              <1> ;	pop	esi
  3935                              <1> ;	retn
  3936                              <1> ;
  3937                              <1> ;swpin_dnp_err:
  3938                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3939                              <1> ;swpin_err_retn:
  3940                              <1> ;	mov	[u.error], eax
  3941                              <1> ;	stc
  3942                              <1> ;	retn
  3943                              <1> ;
  3944                              <1> ;swpin_snp_err:
  3945                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3946                              <1> ;	jmp	short swpin_err_retn
  3947                              <1> 
  3948                              <1> ; 17/04/2021
  3949                              <1> ; ('swap_out' procedure call is disabled as temporary)
  3950                              <1> 
  3951                              <1> ; 30/11/2021 - temporary !
  3952                              <1> ;swap_out:
  3953                              <1> 	; 10/06/2016
  3954                              <1> 	; 07/06/2016
  3955                              <1>         ; 23/05/2016
  3956                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3957                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3958                              <1> 	;
  3959                              <1> 	; INPUT -> 
  3960                              <1> 	;	none
  3961                              <1> 	;
  3962                              <1> 	; OUTPUT ->
  3963                              <1> 	;	EAX = Physical page address (which is swapped out
  3964                              <1> 	;	      for allocating a new page)
  3965                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3966                              <1> 	;		  or sector not present or drive not ready
  3967                              <1> 	;	     EAX = Error code
  3968                              <1> 	;	     [u.error] = EAX 
  3969                              <1> 	;		       = The last error code for the process
  3970                              <1> 	;		         (will be reset after returning to user)	  
  3971                              <1> 	;
  3972                              <1> 	; Modified Registers -> none (except EAX)
  3973                              <1> 	;
  3974                              <1> 
  3975                              <1> ;	cmp 	word [swpq_count], 1
  3976                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3977                              <1> ;
  3978                              <1> ;       ;cmp    dword [swp_drv], 1
  3979                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3980                              <1> ;
  3981                              <1> ;       cmp     dword [swpd_free], 1
  3982                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3983                              <1> ;
  3984                              <1> ;	push	ebx ; *
  3985                              <1> ;swpout_1:
  3986                              <1> ;	; 10/06/2016
  3987                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3988                              <1> ;	call	swap_queue_shift
  3989                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3990                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3991                              <1> ;				       ; pointer in the swap queue
  3992                              <1> ;	; EAX = PTE value of the page
  3993                              <1> ;	; EBX = PTE address of the page
  3994                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3995                              <1> ;	;
  3996                              <1> ;	; 07/06/2016
  3997                              <1> ;	; 19/05/2016
  3998                              <1> ;	; check this page is in timer events or not
  3999                              <1> ;	
  4000                              <1> ;swpout_timer_page_0:
  4001                              <1> ;	push	edx ; **
  4002                              <1> ;
  4003                              <1> ;	; 07/06/2016
  4004                              <1> ;	cmp	byte [timer_events], 0 
  4005                              <1> ;	jna	short swpout_2
  4006                              <1> ;	;
  4007                              <1> ;	mov	dl, [timer_events]
  4008                              <1> ;
  4009                              <1> ;	push	ecx ; ***
  4010                              <1> ;	push	ebx ; ****
  4011                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4012                              <1> ;			       ; structures 
  4013                              <1> ;swpout_timer_page_1:
  4014                              <1> ;	mov	cl, [ebx]
  4015                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4016                              <1> ;	jz	short swpout_timer_page_3
  4017                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4018                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4019                              <1> ;				; of the response byte address, to
  4020                              <1> ;				; get beginning of the page address)
  4021                              <1> ;	cmp	eax, ecx
  4022                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4023                              <1> ;	
  4024                              <1> ;	; !same page!
  4025                              <1> ;	;
  4026                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4027                              <1> ;	; This page will be used by the kernel to put timer event
  4028                              <1> ;	; response (signal return) byte at the requested address;
  4029                              <1> ;	; in order to prevent a possible wrong write (while
  4030                              <1> ;	; this page is swapped out) on physical memory,
  4031                              <1> ;	; we must protect this page against to be swapped out!
  4032                              <1> ;	;
  4033                              <1> ;	pop	ebx ; ****
  4034                              <1> ;	pop	ecx ; ***
  4035                              <1> ;	pop	edx ; **
  4036                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4037                              <1> ; 
  4038                              <1> ;swpout_timer_page_2:
  4039                              <1> ;	; 07/06/2016
  4040                              <1> ;	dec	dl
  4041                              <1> ;	jz	short swpout_timer_page_4
  4042                              <1> ;swpout_timer_page_3:
  4043                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4044                              <1> ;	;jnb	short swpout_timer_page_4
  4045                              <1> ;	add	ebx, 16
  4046                              <1> ;	jmp	short swpout_timer_page_1	
  4047                              <1> ;
  4048                              <1> ;swpout_timer_page_4:
  4049                              <1> ;	pop	ebx ; ****
  4050                              <1> ;	pop	ecx ; ***
  4051                              <1> ;swpout_2:
  4052                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4053                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4054                              <1> ;	;
  4055                              <1> ;	call	link_swap_block
  4056                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4057                              <1> ;				       ; because [swpd_free] value
  4058                              <1> ;				       ; was checked at the beginging. 	
  4059                              <1> ;	pop	edx ; **
  4060                              <1> ;	pop	ebx ; *
  4061                              <1> ;	jmp	short swpout_nfspc_err 
  4062                              <1> ;swpout_3:
  4063                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4064                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4065                              <1> ;	;	
  4066                              <1> ;	push	esi ; **
  4067                              <1> ;	push	ecx ; ***
  4068                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4069                              <1> ;	mov	esi, [swp_drv]	
  4070                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4071                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4072                              <1> ;		; size different than 512 bytes, logical disk sector
  4073                              <1> ;		; size is 512 bytes and disk writing procedure
  4074                              <1> ;		; will be performed for writing 4096 bytes
  4075                              <1> ;		; (2*2048, 8*512). 
  4076                              <1> ;	; ESI = Logical disk description table address
  4077                              <1> ;	; EBX = Buffer (Page) address
  4078                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4079                              <1> ;	; ECX = Sector count ; 8 sectors
  4080                              <1> ;	; edx = PTE address
  4081                              <1> ;	call	logical_disk_write
  4082                              <1> ;	; edx = PTE address
  4083                              <1> ;	pop	ecx ; sector address	
  4084                              <1> ;	jnc	short swpout_write_ok
  4085                              <1> ;	;
  4086                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4087                              <1> ;swpout_dw_err:
  4088                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4089                              <1> ;	mov	[u.error], eax
  4090                              <1> ;	jmp	short swpout_retn
  4091                              <1> ;	;
  4092                              <1> ;swpout_write_ok:
  4093                              <1> ;	; EBX = Buffer (page) address
  4094                              <1> ;	; EDX = Page Table Entry address
  4095                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4096                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4097                              <1> ;	mov 	[edx], ecx 
  4098                              <1> ;		; bit 0 = 0 (swapped page)
  4099                              <1> ;	mov	eax, ebx
  4100                              <1> ;swpout_retn:
  4101                              <1> ;	pop	ecx ; ***
  4102                              <1> ;	pop	esi ; **
  4103                              <1> ;	pop	ebx ; *
  4104                              <1> ;	retn
  4105                              <1> ;
  4106                              <1> ;;swpout_dnp_err:
  4107                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4108                              <1> ;;	jmp	short swpout_err_retn
  4109                              <1> ;swpout_nfspc_err:
  4110                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4111                              <1> ;swpout_err_retn:
  4112                              <1> ;	mov	[u.error], eax
  4113                              <1> ;	;stc
  4114                              <1> ;	retn
  4115                              <1> ;swpout_npts_err:
  4116                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4117                              <1> ;	pop	ebx
  4118                              <1> ;	jmp	short swpout_err_retn
  4119                              <1> ;swpout_im_err:
  4120                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4121                              <1> ;	jmp	short swpout_err_retn
  4122                              <1> 
  4123                              <1> ; 17/04/2021
  4124                              <1> ; ('swap_queue_shift' procedure call is disabled as temporary)
  4125                              <1> 
  4126                              <1> ; 30/11/2021 - temporary !
  4127                              <1> ;swap_queue_shift:
  4128                              <1> 	; 26/03/2017
  4129                              <1> 	; 10/06/2016
  4130                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4131                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4132                              <1> 	;
  4133                              <1> 	; INPUT ->
  4134                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4135                              <1> 	;	      and process number combination (bit 0 to 11)
  4136                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4137                              <1> 	;	
  4138                              <1> 	; OUTPUT ->
  4139                              <1> 	;	If EBX input > 0 
  4140                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4141                              <1> 	; 	   from the tail to the head, up to entry offset
  4142                              <1> 	; 	   which points to EBX input value or nothing
  4143                              <1> 	;	   to do if EBX value is not found on the queue.
  4144                              <1> 	;	   (The entry -with EBX value- will be removed
  4145                              <1> 	;	   from the queue if it is found.)
  4146                              <1> 	;
  4147                              <1> 	;	   EAX = 0		
  4148                              <1> 	;
  4149                              <1> 	;	If EBX input = 0
  4150                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4151                              <1> 	; 	   from the tail to the head, if the PTE address
  4152                              <1> 	;	   which is pointed in head of the queue is marked
  4153                              <1> 	;	   as "accessed" or it is marked as "non present".
  4154                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4155                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4156                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4157                              <1> 	;	   -without dropping pointer of the PTE from 
  4158                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4159                              <1> 	;	   Pointer in the head will be moved into the tail,
  4160                              <1> 	;	   other PTEs will be shifted on head direction.)
  4161                              <1> 	;
  4162                              <1> 	;	   Swap queue will be shifted up to the first
  4163                              <1> 	;	   'present' or 'non accessed' page will be found
  4164                              <1> 	;	   (as pointed) on the queue head (then it will be
  4165                              <1>         ;          removed/dropped from the queue).
  4166                              <1> 	;
  4167                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4168                              <1> 	;		 (it's pointer -virtual address-) dropped
  4169                              <1> 	;		 (removed) from swap queue.
  4170                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4171                              <1> 	;	         which is (it's pointer -virtual address-)
  4172                              <1> 	;		 dropped (removed) from swap queue.
  4173                              <1> 	;
  4174                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4175                              <1> 	;
  4176                              <1> 	; Modified Registers -> EAX, EBX
  4177                              <1> 	;
  4178                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4179                              <1> ;	and	ax, ax
  4180                              <1> ;	jz	short swpqs_retn
  4181                              <1> ;	push	edi
  4182                              <1> ;	push	esi
  4183                              <1> ;	push	ecx
  4184                              <1> ;	mov	esi, swap_queue
  4185                              <1> ;	mov	ecx, eax
  4186                              <1> ;	or	ebx, ebx
  4187                              <1> ;	jz	short swpqs_7
  4188                              <1> ;swpqs_1:
  4189                              <1> ;	lodsd
  4190                              <1> ;	cmp	eax, ebx
  4191                              <1> ;	je	short swpqs_2
  4192                              <1> ;	loop	swpqs_1
  4193                              <1> ;	; 10/06/2016
  4194                              <1> ;	sub	eax, eax 
  4195                              <1> ;	jmp	short swpqs_6
  4196                              <1> ;swpqs_2:
  4197                              <1> ;	mov	edi, esi
  4198                              <1> ;	sub 	edi, 4
  4199                              <1> ;swpqs_3:
  4200                              <1> ;	dec	word [swpq_count]
  4201                              <1> ;	jz	short swpqs_5
  4202                              <1> ;swpqs_4:
  4203                              <1> ;	dec 	ecx
  4204                              <1> ;	rep	movsd	; shift up (to the head)
  4205                              <1> ;swpqs_5:
  4206                              <1> ;	xor	eax, eax
  4207                              <1> ;	mov	[edi], eax
  4208                              <1> ;swpqs_6:
  4209                              <1> ;	pop	ecx
  4210                              <1> ;	pop	esi
  4211                              <1> ;	pop	edi
  4212                              <1> ;swpqs_retn:
  4213                              <1> ;	retn		
  4214                              <1> ;swpqs_7:
  4215                              <1> ;	mov	edi, esi ; head
  4216                              <1> ;	lodsd
  4217                              <1> ;	; 20/07/2015
  4218                              <1> ;	mov	ebx, eax
  4219                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4220                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4221                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4222                              <1> ;		      ; ax = process number (1 to 4095)
  4223                              <1> ;	cmp	al, [u.uno]
  4224                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4225                              <1> ;	jne	short swpqs_8
  4226                              <1> ;	mov	eax, [u.pgdir]
  4227                              <1> ;	jmp	short swpqs_9
  4228                              <1> ;swpqs_8:
  4229                              <1> ;	; 09/06/2016
  4230                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4231                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4232                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4233                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4234                              <1> ;
  4235                              <1> ;	;shl	ax, 2
  4236                              <1> ;	shl	al, 2
  4237                              <1> ;	mov 	eax, [eax+p.upage-4]
  4238                              <1> ;	or	eax, eax
  4239                              <1> ;	jz	short swpqs_3 ; invalid upage
  4240                              <1> ;	add	eax, u.pgdir - user
  4241                              <1> ;			 ; u.pgdir value for the process
  4242                              <1> ;			 ; is in [eax]
  4243                              <1> ;	mov	eax, [eax]
  4244                              <1> ;	and	eax, eax
  4245                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4246                              <1> ;swpqs_9:
  4247                              <1> ;	push	edx
  4248                              <1> ;	; eax = page directory
  4249                              <1> ;	; ebx = virtual address
  4250                              <1> ;	call	get_pte
  4251                              <1> ;	mov	ebx, edx	; PTE address
  4252                              <1> ;	pop	edx
  4253                              <1> ;	; 10/06/2016
  4254                              <1> ;	jc	short swpqs_13 ; empty PDE
  4255                              <1> ;	; EAX = PTE value
  4256                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4257                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4258                              <1> ;			        ; from the queue (head)
  4259                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4260                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4261                              <1> ;			        ; from the queue (head) 	
  4262                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4263                              <1> ;	;jnz	short swpqs_11  ; present
  4264                              <1> ;			        ; accessed page
  4265                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4266                              <1> ;	jc	short swpqs_11  ; accessed page
  4267                              <1> ;
  4268                              <1> ;	dec	ecx
  4269                              <1> ;	mov	[swpq_count], cx
  4270                              <1> ;       jz      short swpqs_10
  4271                              <1> ;		; esi = head + 4
  4272                              <1> ;		; edi = head
  4273                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4274                              <1> ;swpqs_10:
  4275                              <1> ;	mov	[edi], ecx ; 0
  4276                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4277                              <1> ;
  4278                              <1> ;swpqs_11:
  4279                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4280                              <1> ;	; Rotation (head -> tail)
  4281                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4282                              <1> ;	jz	short swpqs_10
  4283                              <1> ;		; esi = head + 4
  4284                              <1> ;		; edi = head
  4285                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4286                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4287                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4288                              <1> ;
  4289                              <1> ;	mov	cx, [swpq_count]
  4290                              <1> ;
  4291                              <1> ;swpqs_12:
  4292                              <1> ;	mov	esi, swap_queue ; head
  4293                              <1> ;       jmp     swpqs_7
  4294                              <1> ;
  4295                              <1> ;swpqs_13:
  4296                              <1> ;	dec	ecx
  4297                              <1> ;	mov	[swpq_count], cx
  4298                              <1> ;       jz      swpqs_5
  4299                              <1> ;	jmp	short swpqs_12
  4300                              <1> 
  4301                              <1> ; 17/04/2021
  4302                              <1> ; ('add_to_swp_queue' procedure call is disabled as temporary)
  4303                              <1> 
  4304                              <1> ; 30/11/2021 - temporary !
  4305                              <1> ;add_to_swap_queue:
  4306                              <1> 	; 20/02/2017
  4307                              <1> 	; 20/07/2015
  4308                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4309                              <1> 	;
  4310                              <1> 	; Adds new page to swap queue
  4311                              <1> 	; (page directories and page tables must not be added
  4312                              <1> 	; to swap queue)	
  4313                              <1> 	;
  4314                              <1> 	; INPUT ->
  4315                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4316                              <1> 	;	[u.uno]
  4317                              <1> 	;	20/02/2017
  4318                              <1> 	;	(Linear address = CORE + user's virtual address)
  4319                              <1> 	;
  4320                              <1> 	; OUTPUT ->
  4321                              <1> 	;	EAX = [swpq_count]
  4322                              <1> 	;	      (after the PTE has been added)
  4323                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4324                              <1> 	;	      the PTE could not be added.
  4325                              <1> 	;
  4326                              <1> 	; Modified Registers -> EAX
  4327                              <1> 	;
  4328                              <1> ;	push	ebx
  4329                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4330                              <1> ;	mov	bl, [u.uno] ; current process number
  4331                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4332                              <1> ;				 ; it is already on the queue
  4333                              <1> ;		; then add it to the tail of the queue
  4334                              <1> ;	movzx	eax, word [swpq_count]
  4335                              <1> ;	cmp	ax, 1024
  4336                              <1> ;	jb	short atsq_1
  4337                              <1> ;	sub	ax, ax
  4338                              <1> ;	pop	ebx
  4339                              <1> ;	retn
  4340                              <1> ;atsq_1:
  4341                              <1> ;	push	esi
  4342                              <1> ;	mov	esi, swap_queue
  4343                              <1> ;	and	ax, ax
  4344                              <1> ;	jz	short atsq_2
  4345                              <1> ;	shl	ax, 2	; convert to offset
  4346                              <1> ;	add	esi, eax
  4347                              <1> ;	shr	ax, 2
  4348                              <1> ;atsq_2:
  4349                              <1> ;	inc	ax
  4350                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4351                              <1> ;	mov	[swpq_count], ax
  4352                              <1> ;	pop	esi
  4353                              <1> ;	pop	ebx
  4354                              <1> ;	retn
  4355                              <1> 
  4356                              <1> ; 17/04/2021
  4357                              <1> ; ('unlink_swap_block' procedure call is disabled as temporary)
  4358                              <1> 
  4359                              <1> ; 30/11/2021 - temporary !
  4360                              <1> ;unlink_swap_block:
  4361                              <1> 	; 15/09/2015
  4362                              <1> 	; 30/04/2015
  4363                              <1> 	; 18/04/2015
  4364                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4365                              <1> 	;
  4366                              <1> 	; INPUT -> 
  4367                              <1> 	;	EAX = swap disk/file offset address
  4368                              <1> 	;	      (bit 1 to bit 31)
  4369                              <1> 	; OUTPUT ->
  4370                              <1> 	;	[swpd_free] is increased
  4371                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4372                              <1> 	;
  4373                              <1> 	; Modified Registers -> EAX
  4374                              <1> 	;
  4375                              <1> ;	push	ebx
  4376                              <1> ;	push	edx
  4377                              <1> ;	;
  4378                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4379                              <1> ;				     ; 3 bits right
  4380                              <1> ;				     ; to get swap block/page number
  4381                              <1> ;	mov	edx, eax
  4382                              <1> ;	; 15/09/2015
  4383                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4384                              <1> ;				     ; (1 allocation bit = 1 page)
  4385                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4386                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4387                              <1> ;				     ; (to get 32 bit position)			
  4388                              <1> ;	;
  4389                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4390                              <1> ;	add	ebx, edx
  4391                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4392                              <1> ;				     ; (allocation bit position)	 
  4393                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4394                              <1> ;				     ; than the address in 'swpd_next' ?
  4395                              <1> ;				     ; (next/first free block value)		
  4396                              <1> ;	jnb	short uswpbl_1	     ; no	
  4397                              <1> ;	mov	[swpd_next], eax     ; yes	
  4398                              <1> ;uswpbl_1:
  4399                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4400                              <1> ;				     ; set relevant bit to 1.
  4401                              <1> ;				     ; set CF to the previous bit value	
  4402                              <1> ;	cmc			     ; complement carry flag	
  4403                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4404                              <1> ;				     ; if the block is already deallocated
  4405                              <1> ;				     ; before.	
  4406                              <1> ;       inc     dword [swpd_free]
  4407                              <1> ;uswpbl_2:
  4408                              <1> ;	pop	edx
  4409                              <1> ;	pop	ebx
  4410                              <1> ;	retn
  4411                              <1> 
  4412                              <1> ; 17/04/2021
  4413                              <1> ; ('link_swap_block' procedure call is disabled as temporary)
  4414                              <1> 
  4415                              <1> ; 30/11/2021 - temporary !
  4416                              <1> ;link_swap_block:
  4417                              <1> 	; 01/07/2015
  4418                              <1> 	; 18/04/2015
  4419                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4420                              <1> 	;
  4421                              <1> 	; INPUT -> none
  4422                              <1> 	;
  4423                              <1> 	; OUTPUT ->
  4424                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4425                              <1> 	;	      in sectors (corresponding 
  4426                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4427                              <1> 	;
  4428                              <1> 	;	CF = 1 and EAX = 0 
  4429                              <1> 	; 		   if there is not a free block to be allocated	
  4430                              <1> 	;
  4431                              <1> 	; Modified Registers -> none (except EAX)
  4432                              <1> 	;
  4433                              <1> 
  4434                              <1> ;	;mov	eax, [swpd_free]
  4435                              <1> ;	;and	eax, eax
  4436                              <1> ;	;jz	short out_of_swpspc
  4437                              <1> ;	;
  4438                              <1> ;	push	ebx
  4439                              <1> ;	push	ecx
  4440                              <1> ;	;
  4441                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4442                              <1> ;	mov	ecx, ebx
  4443                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4444                              <1> ;				 ; next_free_swap_block >> 5
  4445                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4446                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4447                              <1> ;lswbl_scan:
  4448                              <1> ;	cmp	ebx, ecx
  4449                              <1> ;	ja	short lswbl_notfound
  4450                              <1> ;	;
  4451                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4452                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4453                              <1> ;			   ; loads the destination with an index to
  4454                              <1> ;			   ; first set bit. (0 -> 31) 
  4455                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4456                              <1> ;	; 01/07/2015
  4457                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4458                              <1> ;			 ;
  4459                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4460                              <1> ;			 ;	  with value of 1 means 
  4461                              <1> ;			 ;	  the corresponding page is free 
  4462                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4463                              <1> ;	add	ebx, 4
  4464                              <1> ;			 ; We return back for searching next page block
  4465                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4466                              <1> ;			 ;	 we always will find at least 1 free block here.
  4467                              <1> ;	jmp    	short lswbl_scan
  4468                              <1> ;	;
  4469                              <1> ;lswbl_notfound:	
  4470                              <1> ;	sub	ecx, swap_alloc_table
  4471                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4472                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4473                              <1> ;	xor	eax, eax
  4474                              <1> ;	mov	[swpd_free], eax
  4475                              <1> ;	stc
  4476                              <1> ;lswbl_ok:
  4477                              <1> ;	pop	ecx
  4478                              <1> ;	pop	ebx
  4479                              <1> ;	retn
  4480                              <1> ;	;
  4481                              <1> ;;out_of_swpspc:
  4482                              <1> ;;	stc
  4483                              <1> ;;	retn
  4484                              <1> ;
  4485                              <1> ;lswbl_found:
  4486                              <1> ;	mov	ecx, ebx
  4487                              <1> ;	sub	ecx, swap_alloc_table
  4488                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4489                              <1> ;				 ; address/offset (to the next)
  4490                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4491                              <1> ;	;
  4492                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4493                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4494                              <1> ;				 ; in the destination.
  4495                              <1> ;				 ;
  4496                              <1> ;				 ; Reset the bit which is corresponding to the 
  4497                              <1> ;				 ; (just) allocated block.
  4498                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4499                              <1> ;	add	eax, ecx	 ; = block number
  4500                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4501                              <1> ;				 ; 1 block =  8 sectors
  4502                              <1> ;	;
  4503                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4504                              <1> ;	;
  4505                              <1> ;	; NOTE: The relevant page table entry will be updated
  4506                              <1> ;	;       according to this EAX value...
  4507                              <1> ;	;
  4508                              <1> ;	jmp	short lswbl_ok
  4509                              <1> 
  4510                              <1> ; 17/04/2021
  4511                              <1> ; ('logical_disk_read' procedure call is disabled as temporary)
  4512                              <1> 
  4513                              <1> ; 30/11/2021 - temporary !
  4514                              <1> ;logical_disk_read:
  4515                              <1> 	; 20/07/2015
  4516                              <1> 	; 09/03/2015 (temporary code here)
  4517                              <1> 	;
  4518                              <1> 	; INPUT ->
  4519                              <1> 	; 	ESI = Logical disk description table address
  4520                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4521                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4522                              <1> 	; 	ECX = Sector count
  4523                              <1> 	;
  4524                              <1> 	;
  4525                              <1> ;	retn
  4526                              <1> 
  4527                              <1> ; 17/04/2021
  4528                              <1> ; ('logical_disk_write' procedure call is disabled as temporary)
  4529                              <1> 
  4530                              <1> ; 30/11/2021 - temporary !
  4531                              <1> ;logical_disk_write:
  4532                              <1> 	; 20/07/2015
  4533                              <1> 	; 09/03/2015 (temporary code here)
  4534                              <1> 	;
  4535                              <1> 	; INPUT ->
  4536                              <1> 	; 	ESI = Logical disk description table address
  4537                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4538                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4539                              <1> 	; 	ECX = Sector count
  4540                              <1> 	;
  4541                              <1> ;	retn
  4542                              <1> 
  4543                              <1> get_physical_addr:
  4544                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  4545                              <1> 	;	(temporary modifications)
  4546                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4547                              <1> 	; 18/10/2015
  4548                              <1> 	; 29/07/2015
  4549                              <1> 	; 20/07/2015
  4550                              <1> 	; 04/06/2015
  4551                              <1> 	; 20/05/2015
  4552                              <1> 	; 28/04/2015
  4553                              <1> 	; 18/04/2015
  4554                              <1> 	; Get physical address
  4555                              <1> 	;     (allocates a new page for user if it is not present)
  4556                              <1> 	;	
  4557                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4558                              <1> 	; (buffer) address to physical address (of the buffer).)
  4559                              <1> 	; ('sys write', 'sys read' system calls...)
  4560                              <1> 	;
  4561                              <1> 	; INPUT ->
  4562                              <1> 	;	EBX = virtual address
  4563                              <1> 	;	u.pgdir = page directory (physical) address
  4564                              <1> 	;
  4565                              <1> 	; OUTPUT ->
  4566                              <1> 	;	EAX = physical address 
  4567                              <1> 	;	EBX = linear address	
  4568                              <1> 	;	EDX = physical address of the page frame
  4569                              <1> 	;	      (with attribute bits)
  4570                              <1> 	;	ECX = byte count within the page frame
  4571                              <1> 	;
  4572                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4573                              <1> 	;
  4574                              <1> 
  4575                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4576 000031A0 A1[0C760000]        <1> 	mov	eax, [u.pgdir]
  4577                              <1> 
  4578                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4579                              <1> 	
  4580 000031A5 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4581                              <1> 	;
  4582                              <1> 	;mov	eax, [u.pgdir]
  4583 000031AB E816FDFFFF          <1> 	call	get_pte
  4584                              <1> 		; EDX = Page table entry address (if CF=0)
  4585                              <1> 	        ;       Page directory entry address (if CF=1)
  4586                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4587                              <1> 		; EAX = Page table entry value (page address)
  4588                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4589 000031B0 731C                <1> 	jnc	short gpa_1
  4590                              <1> 	;
  4591 000031B2 E8FDFBFFFF          <1> 	call	allocate_page
  4592 000031B7 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4593                              <1> gpa_0:
  4594 000031B9 E867FCFFFF          <1> 	call 	clear_page
  4595                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4596 000031BE 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4597                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4598                              <1> 			   ; (user, writable, present page)	
  4599 000031C0 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4600 000031C2 A1[0C760000]        <1> 	mov	eax, [u.pgdir]	
  4601 000031C7 E8FAFCFFFF          <1> 	call	get_pte
  4602 000031CC 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4603                              <1> gpa_1:
  4604                              <1> 	; EAX = PTE value, EDX = PTE address
  4605 000031CE A801                <1> 	test 	al, PTE_A_PRESENT
  4606 000031D0 750A                <1> 	jnz	short gpa_3
  4607 000031D2 09C0                <1> 	or	eax, eax
  4608 000031D4 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4609                              <1> 
  4610                              <1> ; 17/04/2021
  4611                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4612 000031D6 EB2C                <1> 	jmp	short gpa_im_err  ; temporary !
  4613                              <1> 
  4614                              <1> 	; 20/07/2015
  4615                              <1> ;	push	ebp
  4616                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4617                              <1> ;	; reload swapped page
  4618                              <1> ;	call	reload_page ; 28/04/2015
  4619                              <1> ;	pop	ebp
  4620                              <1> ;	jc	short gpa_retn
  4621                              <1> gpa_2:
  4622                              <1> ; 17/04/2021
  4623                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  4624                              <1> 
  4625                              <1> 	; 20/07/2015
  4626                              <1> 	; 20/05/2015
  4627                              <1> 	; add this page to swap queue
  4628                              <1> ;	push	eax 
  4629                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4630                              <1> ;	call 	add_to_swap_queue
  4631                              <1> ;	pop	eax
  4632                              <1> 		; PTE address in EDX
  4633                              <1> 		; virtual address in EBX
  4634                              <1> 
  4635                              <1> 	; EAX = memory page address
  4636 000031D8 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4637                              <1> 				  ; present flag, bit 0 = 1
  4638                              <1> 				  ; user flag, bit 2 = 1	
  4639                              <1> 				  ; writable flag, bit 1 = 1
  4640 000031DA 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4641                              <1> gpa_3:
  4642                              <1> 	; 18/10/2015
  4643 000031DC 89D9                <1> 	mov	ecx, ebx
  4644 000031DE 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4645 000031E4 89C2                <1> 	mov 	edx, eax
  4646 000031E6 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4647 000031EA 01C8                <1> 	add	eax, ecx
  4648 000031EC F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4649 000031EE 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4650 000031F4 F8                  <1> 	clc
  4651                              <1> gpa_retn:
  4652 000031F5 C3                  <1> 	retn	
  4653                              <1> gpa_4:	
  4654 000031F6 E8B9FBFFFF          <1> 	call	allocate_page
  4655 000031FB 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4656 000031FD E823FCFFFF          <1> 	call	clear_page
  4657 00003202 EBD4                <1> 	jmp	short gpa_2
  4658                              <1> 
  4659                              <1> gpa_im_err:	
  4660 00003204 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4661                              <1> 				  ; Major error = 0 (No protection fault)	
  4662 00003209 C3                  <1> 	retn
  4663                              <1> 
  4664                              <1> ; 17/04/2021
  4665                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4666                              <1> 
  4667                              <1> ; 30/11/2021 - temporary !
  4668                              <1> ;reload_page:
  4669                              <1> 	; 20/07/2015
  4670                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4671                              <1> 	;
  4672                              <1> 	; Reload (Restore) swapped page at memory
  4673                              <1> 	;
  4674                              <1> 	; INPUT -> 
  4675                              <1> 	;	EBP = Virtual (linear) memory address
  4676                              <1> 	;	EAX = PTE value (swap disk sector address)
  4677                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4678                              <1> 	; OUTPUT ->
  4679                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4680                              <1> 	;
  4681                              <1> 	;	CF = 1 and EAX = error code
  4682                              <1> 	;
  4683                              <1> 	; Modified Registers -> none (except EAX)
  4684                              <1> 	;
  4685                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4686                              <1> ;	push	ebx      ;
  4687                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4688                              <1> ;	call	allocate_page
  4689                              <1> ;	jc	short rlp_im_err
  4690                              <1> ;	xchg 	eax, ebx	
  4691                              <1> ;	; EBX = Physical memory (page) address
  4692                              <1> ;	; EAX = Swap disk (offset) address
  4693                              <1> ;	; EBP = Virtual (linear) memory address
  4694                              <1> ;	call	swap_in
  4695                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4696                              <1> ;	mov	eax, ebx	
  4697                              <1> ;rlp_retn:
  4698                              <1> ;	pop	ebx
  4699                              <1> ;	retn
  4700                              <1> ;	
  4701                              <1> ;rlp_im_err:	
  4702                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4703                              <1> ;				  ; Major error = 0 (No protection fault)	
  4704                              <1> ;	jmp	short rlp_retn
  4705                              <1> ;
  4706                              <1> ;rlp_swp_err:
  4707                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4708                              <1> ;	jmp	short rlp_retn
  4709                              <1> 
  4710                              <1> copy_page_dir:
  4711                              <1> 	; 17/04/2021 (temporary modifications)
  4712                              <1> 	; 19/09/2015
  4713                              <1> 	; temporary - 07/09/2015
  4714                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4715                              <1> 	;
  4716                              <1> 	; INPUT -> 
  4717                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4718                              <1> 	;		    page directory.
  4719                              <1> 	; OUTPUT ->
  4720                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4721                              <1> 	;	       page directory.
  4722                              <1> 	;	(New page directory with new page table entries.)
  4723                              <1> 	;	(New page tables with read only copies of the parent's
  4724                              <1> 	;	pages.)
  4725                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4726                              <1> 	;
  4727                              <1> 	; Modified Registers -> none (except EAX)
  4728                              <1> 	;
  4729 0000320A E8A5FBFFFF          <1> 	call	allocate_page
  4730 0000320F 723E                <1> 	jc	short cpd_err
  4731                              <1> 	;
  4732 00003211 55                  <1> 	push	ebp ; 20/07/2015
  4733 00003212 56                  <1> 	push	esi
  4734 00003213 57                  <1> 	push	edi
  4735 00003214 53                  <1> 	push	ebx
  4736 00003215 51                  <1> 	push	ecx
  4737 00003216 8B35[0C760000]      <1> 	mov	esi, [u.pgdir]
  4738 0000321C 89C7                <1> 	mov	edi, eax
  4739 0000321E 50                  <1> 	push	eax ; save child's page directory address
  4740                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4741                              <1> 	; (use same system space for all user page tables) 
  4742 0000321F A5                  <1> 	movsd
  4743 00003220 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4744 00003225 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4745                              <1> cpd_0:	
  4746 0000322A AD                  <1> 	lodsd
  4747                              <1> 	;or	eax, eax
  4748                              <1>         ;jnz	short cpd_1
  4749 0000322B A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4750 0000322D 7508                <1> 	jnz	short cpd_1
  4751                              <1>  	; (virtual address at the end of the page table)	
  4752 0000322F 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4753 00003235 EB0F                <1> 	jmp	short cpd_2
  4754                              <1> cpd_1:	
  4755 00003237 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4756 0000323B 89C3                <1> 	mov	ebx, eax
  4757                              <1> 	; EBX = Parent's page table address
  4758 0000323D E81F000000          <1> 	call	copy_page_table
  4759 00003242 720C                <1> 	jc	short cpd_p_err
  4760                              <1> 	; EAX = Child's page table address
  4761 00003244 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4762                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4763                              <1> 			 ; (present, writable, user)
  4764                              <1> cpd_2:
  4765 00003246 AB                  <1> 	stosd
  4766 00003247 E2E1                <1> 	loop	cpd_0
  4767                              <1> 	;
  4768 00003249 58                  <1> 	pop	eax  ; restore child's page directory address
  4769                              <1> cpd_3:
  4770 0000324A 59                  <1> 	pop	ecx
  4771 0000324B 5B                  <1> 	pop	ebx
  4772 0000324C 5F                  <1> 	pop	edi
  4773 0000324D 5E                  <1> 	pop	esi
  4774 0000324E 5D                  <1> 	pop	ebp
  4775                              <1> cpd_err:
  4776 0000324F C3                  <1> 	retn
  4777                              <1> cpd_p_err:
  4778                              <1> 	; release the allocated pages missing (recover free space)
  4779 00003250 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4780 00003251 8B1D[0C760000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4781 00003257 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4782 0000325C 29C0                <1> 	sub	eax, eax ; 0
  4783 0000325E F9                  <1> 	stc
  4784 0000325F EBE9                <1> 	jmp	short cpd_3	
  4785                              <1> 
  4786                              <1> copy_page_table:
  4787                              <1> 	; 17/04/2021 (temporary modifications)
  4788                              <1> 	; 19/09/2015
  4789                              <1> 	; temporary - 07/09/2015
  4790                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4791                              <1> 	;
  4792                              <1> 	; INPUT -> 
  4793                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4794                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4795                              <1> 	; OUTPUT ->
  4796                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4797                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4798                              <1> 	;	CF = 1 -> error 
  4799                              <1> 	;
  4800                              <1> 	; Modified Registers -> EBP (except EAX)
  4801                              <1> 	;
  4802 00003261 E84EFBFFFF          <1> 	call	allocate_page
  4803 00003266 7244                <1> 	jc	short cpt_err
  4804                              <1> 	;
  4805 00003268 50                  <1> 	push	eax ; *
  4806                              <1> 	;push 	ebx
  4807 00003269 56                  <1> 	push	esi
  4808 0000326A 57                  <1> 	push	edi
  4809 0000326B 52                  <1> 	push	edx
  4810 0000326C 51                  <1> 	push	ecx
  4811                              <1> 	;
  4812 0000326D 89DE                <1> 	mov	esi, ebx
  4813 0000326F 89C7                <1> 	mov	edi, eax
  4814 00003271 89C2                <1> 	mov	edx, eax
  4815 00003273 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4816                              <1> cpt_0:
  4817 00003279 AD                  <1> 	lodsd
  4818 0000327A A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4819                              <1> 	;jnz	short cpt_1 (*)
  4820                              <1> 	; 17/04/2021 (temporary (*)
  4821                              <1> 	;and	eax, eax (*)
  4822 0000327C 741E                <1> 	jz	short cpt_2  ; 17/04/2021
  4823                              <1> 	
  4824                              <1> ; 17/04/2021
  4825                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4826                              <1> ;
  4827                              <1> ;	; ebp = virtual (linear) address of the memory page
  4828                              <1> ;	call	reload_page ; 28/04/2015
  4829                              <1> ;	jc	short cpt_p_err
  4830                              <1> cpt_1:
  4831 0000327E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4832 00003282 89C1                <1> 	mov	ecx, eax
  4833                              <1> 	; Allocate a new page for the child process
  4834 00003284 E82BFBFFFF          <1> 	call	allocate_page
  4835 00003289 721C                <1> 	jc	short cpt_p_err
  4836 0000328B 57                  <1> 	push	edi
  4837 0000328C 56                  <1> 	push	esi
  4838 0000328D 89CE                <1> 	mov	esi, ecx
  4839 0000328F 89C7                <1> 	mov	edi, eax
  4840 00003291 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4841 00003296 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4842 00003298 5E                  <1> 	pop	esi
  4843 00003299 5F                  <1> 	pop	edi
  4844                              <1> 	; 
  4845                              <1> ; 17/04/2021
  4846                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)	
  4847                              <1> ;
  4848                              <1> ;	push	ebx
  4849                              <1> ;	push	eax
  4850                              <1> ;	mov	ebx, ebp
  4851                              <1> ;	; ebx = virtual address of the memory page
  4852                              <1> ;	call	add_to_swap_queue
  4853                              <1> ;	pop	eax
  4854                              <1> ;	pop	ebx
  4855                              <1> 	;
  4856                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4857 0000329A 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4858                              <1> cpt_2:
  4859 0000329C AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4860                              <1> 	;
  4861 0000329D 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4862                              <1> 	;
  4863 000032A3 39D7                <1> 	cmp	edi, edx
  4864 000032A5 72D2                <1> 	jb	short cpt_0
  4865                              <1> cpt_p_err:
  4866 000032A7 59                  <1> 	pop	ecx
  4867 000032A8 5A                  <1> 	pop	edx
  4868 000032A9 5F                  <1> 	pop	edi
  4869 000032AA 5E                  <1> 	pop	esi
  4870                              <1> 	;pop	ebx
  4871 000032AB 58                  <1> 	pop	eax ; *
  4872                              <1> cpt_err:
  4873 000032AC C3                  <1> 	retn
  4874                              <1> 
  4875                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4876                              <1> 
  4877                              <1> ;; Data:
  4878                              <1> 
  4879                              <1> ; 09/03/2015
  4880                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4881                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4882                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  4883                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4884                              <1> ;swpd_next:  dd 0 ; next free page block
  4885                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2085                                  %include 'sysdefs.s' ; 09/03/2015
  2086                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2087                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2088                              <1> ; ****************************************************************************
  2089                              <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC
  2090                              <1> ; Last Modification: 08/02/2022
  2091                              <1> ;
  2092                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2093                              <1> ; (Modified from 
  2094                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2095                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2096                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2097                              <1> ; ----------------------------------------------------------------------------
  2098                              <1> ;
  2099                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2100                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2101                              <1> ; <Bell Laboratories (17/3/1972)>
  2102                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2103                              <1> ;
  2104                              <1> ; ****************************************************************************
  2105                              <1> 
  2106                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2107                              <1> ; (SB structure has been moved here from 'ux.s' 
  2108                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2109                              <1> ; (('ux.s' bss section addresses are being overlapped
  2110                              <1> ;    when SB structure is defined in 'ux.s'))
  2111                              <1> 
  2112                              <1> struc SB ; SuperBlock
  2113                              <1> 
  2114 00000000 ????????            <1> .Header:	resd 1
  2115                              <1> ;.HiddenSects:
  2116 00000004 ????????            <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2117                              <1> ;.TotalSects:
  2118 00000008 ????????            <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)
  2119 0000000C ????????            <1> .Version:	resd 1	
  2120 00000010 ????????            <1> .BlockSize:	resd 1	
  2121 00000014 ????????            <1> .InodeCount:	resd 1	
  2122 00000018 ????????            <1> .FreeMapAddr:	resd 1	
  2123 0000001C ????????            <1> .FreeMapSize:	resd 1	
  2124 00000020 ????????            <1> .InodeMapAddr:	resd 1	
  2125 00000024 ????????            <1> .InodeMapSize:	resd 1	
  2126 00000028 ????????            <1> .InodeTblAddr:	resd 1	
  2127 0000002C ????????            <1> .InodeTblSize:	resd 1	
  2128 00000030 ????????            <1> .FreeInodes:	resd 1	
  2129 00000034 ????????            <1> .FirstFreeIno:	resd 1	
  2130 00000038 ????????            <1> .FreeBlocks:	resd 1	
  2131 0000003C ????????            <1> .FirstFreeBlk:	resd 1	
  2132 00000040 <res 13h>           <1> .BootSecParms:	resb 19	; v1
  2133 00000053 ??????????          <1> .BSExtension:	resb 5	; v2 HDFS
  2134 00000058 ??                  <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2135 00000059 ??                  <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2136 0000005A ????                <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2137 0000005C ????????            <1> .ModifTime:	resd 1	; (last) modification time (*)
  2138 00000060 ????????            <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2139 00000064 ????????            <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2140 00000068 ??                  <1> .LBA_rw:	resb 1
  2141 00000069 ??                  <1> .ClusterSize:	resb 1
  2142 0000006A ??                  <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2143 0000006B ??                  <1> .Mounted:	resb 1
  2144 0000006C ????????            <1> .MountInode:	resd 1  ; double word
  2145 00000070 ??                  <1> .DevMajor:	resb 1
  2146 00000071 ??                  <1> .DevMinor:	resb 1
  2147 00000072 ??                  <1> .LongName:	resb 1
  2148 00000073 ??                  <1> .Direntry32:	resb 1
  2149                              <1> ; 18/07/2021
  2150 00000074 ????????            <1> .FileBuffer:	resd 1
  2151 00000078 ????????            <1> .ItabBuffer:	resd 1
  2152 0000007C ????????            <1> .ImapBuffer:	resd 1
  2153 00000080 ????????            <1> .FmapBuffer:	resd 1
  2154                              <1>  ; 15/07/2021
  2155 00000084 ????????            <1> .LastInode:	resd 1
  2156                              <1> ; 02/05/2021
  2157 00000088 ????????            <1> .FmapIndex:	resd 1
  2158 0000008C ????????            <1> .ImapIndex:	resd 1
  2159 00000090 ????????            <1> .ItableIndex:	resd 1
  2160 00000094 <res 168h>          <1> .Reserved:	resb 508-148 ; 18/07/2021
  2161 000001FC ????????            <1> .Footer:	resd 1
  2162                              <1> 
  2163                              <1> endstruc
  2164                              <1> 
  2165                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2166                              <1> ; (file structure has been moved here from 'ux.s' 
  2167                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2168                              <1> ; (('ux.s' bss section addresses are being overlapped
  2169                              <1> ;    when file structure is defined in 'ux.s'))
  2170                              <1> 
  2171                              <1> ; 22/11/2021
  2172                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision
  2173                              <1> 
  2174                              <1> struc file	; open files (fsp) structure
  2175 00000000 ????                <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  2176 00000002 ????                <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  2177 00000004 ??                  <1>   .drive:  resb 1  ; logical drive (disk) number
  2178 00000005 ??                  <1>   .flags:  resb 1  ; open mode and status
  2179 00000006 ??                  <1>   .count:  resb 1  ; number of processes that have file open
  2180                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  2181 00000007 ??                  <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  2182 00000008 ????????            <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  2183 0000000C ????????            <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  2184                              <1>  .size:  ; = 16		
  2185                              <1> endstruc 
  2186                              <1> 
  2187                              <1> nproc 	equ	16  ; number of processes
  2188                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2189                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2190                              <1> nfiles  equ	50  ; NFILES equ 50 ; 02/01/2022
  2191                              <1> 
  2192                              <1> ; 27/12/2021
  2193                              <1> ;NFILES	  equ   32  ; temporary ! ( 27/12/2021)
  2194                              <1> ; 02/01/2022
  2195                              <1> ;OPENFILES equ	10  ; open files (for user) ; 28/03/2020
  2196                              <1> 
  2197                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2198                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2199                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2200                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2201                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2202                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2203                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2204                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2205                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2206                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2207                              <1> 	; '/core' dump file size = 32768 bytes
  2208                              <1>  
  2209                              <1> ; 08/03/2014 
  2210                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)
  2211                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2212                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2213                              <1> 
  2214                              <1> ; 30/08/2013
  2215                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2216                              <1> 
  2217                              <1> ; 05/02/2014
  2218                              <1> ; process status
  2219                              <1> ;SFREE 	equ 0
  2220                              <1> ;SRUN	equ 1
  2221                              <1> ;SWAIT	equ 2
  2222                              <1> ;SZOMB	equ 3
  2223                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2224                              <1> 
  2225                              <1> ; 09/03/2015
  2226                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2227                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2228                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2229                              <1> 
  2230                              <1> ; 17/09/2015
  2231                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2232                              <1> 
  2233                              <1> ; 12/01/2022 (37,38,39)
  2234                              <1> ; 21/09/2015 (36) 
  2235                              <1> ; 01/07/2015 (35)
  2236                              <1> ; 14/07/2013 (0-34)
  2237                              <1> ; UNIX v1 system calls
  2238                              <1> _rele 	equ 0
  2239                              <1> _exit 	equ 1
  2240                              <1> _fork 	equ 2
  2241                              <1> _read 	equ 3
  2242                              <1> _write	equ 4
  2243                              <1> _open	equ 5
  2244                              <1> _close 	equ 6
  2245                              <1> _wait 	equ 7
  2246                              <1> _creat 	equ 8
  2247                              <1> _link 	equ 9
  2248                              <1> _unlink	equ 10
  2249                              <1> _exec	equ 11
  2250                              <1> _chdir	equ 12
  2251                              <1> _time 	equ 13
  2252                              <1> _mkdir 	equ 14
  2253                              <1> _chmod	equ 15
  2254                              <1> _chown	equ 16
  2255                              <1> _break	equ 17
  2256                              <1> _stat	equ 18
  2257                              <1> _seek	equ 19
  2258                              <1> _tell 	equ 20
  2259                              <1> _mount	equ 21
  2260                              <1> _umount	equ 22
  2261                              <1> _setuid	equ 23
  2262                              <1> _getuid	equ 24
  2263                              <1> _stime	equ 25
  2264                              <1> _quit	equ 26	
  2265                              <1> _intr	equ 27
  2266                              <1> _fstat	equ 28
  2267                              <1> _emt 	equ 29
  2268                              <1> _mdate 	equ 30
  2269                              <1> _stty 	equ 31
  2270                              <1> _gtty	equ 32
  2271                              <1> _ilgins	equ 33
  2272                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2273                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2274                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2275                              <1> ; 12/01/2022 - Retro UNIX 386 v1.2
  2276                              <1> ; Retro UNIX 386 v2 system calls
  2277                              <1> _setgid	equ 37
  2278                              <1> _getgid	equ 38
  2279                              <1> _sysver	equ 39 ; (get) Retro Unix 386 version
  2280                              <1> 
  2281                              <1> %macro sys 1-4
  2282                              <1>     ; 13/04/2015
  2283                              <1>     ; Retro UNIX 386 v1 system call.
  2284                              <1>     mov eax, %1
  2285                              <1>     %if %0 >= 2   
  2286                              <1>         mov ebx, %2
  2287                              <1>         %if %0 >= 3    
  2288                              <1>             mov ecx, %3
  2289                              <1>             %if %0 = 4
  2290                              <1>                mov edx, %4   
  2291                              <1>             %endif
  2292                              <1>         %endif
  2293                              <1>     %endif
  2294                              <1>     int 30h	   
  2295                              <1> %endmacro
  2296                              <1> 
  2297                              <1> ; 13/05/2015 - ERROR CODES
  2298                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2299                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2300                              <1> ; 14/05/2015
  2301                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2302                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2303                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2304                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error
  2305                              <1> ; 16/05/2015		
  2306                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2307                              <1> ; 18/05/2015
  2308                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2309                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2310                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2311                              <1> ; 07/06/2015
  2312                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2313                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2314                              <1> ; 09/06/2015
  2315                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2316                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2317                              <1> ; 16/06/2015
  2318                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2319                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2320                              <1> ; 22/06/2015
  2321                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2322                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2323                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2324                              <1> ; 23/06/2015
  2325                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2326                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2327                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2328                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2329                              <1> ; 27/06/2015
  2330                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2331                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2332                              <1> ; 29/06/2015
  2333                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error
  2334                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2335                              <1> ; 08/02/2022 
  2336                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2337                              <1> ; 10/10/2016
  2338                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2339                              <1> ; 18/05/2016
  2340                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2341                              <1> ; 15/10/2016
  2342                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2343                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2344                              <1> ; 16/10/2016
  2345                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2346                              <1> ; 08/02/2022
  2347                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2348                              <1> 
  2349                              <1> ; 26/08/2015
  2350                              <1> ; 24/07/2015
  2351                              <1> ; 24/06/2015
  2352                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2353                              <1> ; 01/07/2015
  2354                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2355                              <1> ;
  2356                              <1> ; 26/11/2021 ('no free blocks on disk !' error)
  2357                              <1> ERR_ALLOC	   equ 33  ; 'disk allocation error !'	
  2358                              <1> ; 22/11/2021
  2359                              <1> ERR_READ_ONLY_FS   equ 30  ; 'read only file system !' error
  2360                              <1> ; 28/11/2021
  2361                              <1> ERR_INV_FILE	   equ 255 ; 'invalid file (inode) !' error
  2362                              <1> ; 04/12/2021
  2363                              <1> ERR_PERM_DENIED	   equ 11  ; 'permission denied !' error
  2364                              <1> ; 11/12/2021
  2365                              <1> ERR_INV_FUNC	   equ 1   ; 'invalid system call !' error
  2366                              <1> ; 10/01/2022
  2367                              <1> ERR_INO_ALLOC	   equ 33  ; 'inode allocation error !'
  2368                              <1> ERR_NOT_REGULAR    equ 255 ; 'not regular file directory !' error
  2369                              <1> 
  2370                              <1> ; 12/01/2022 - Retro UNIX 386 v1.2
  2371                              <1> %define s.time systm+504 ; boot/sysinit time (or current time)
  2372                              <1> 		
  2086                                  %include 'u0.s'      ; 15/03/2015
  2087                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2088                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2089                              <1> ; ****************************************************************************
  2090                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS0.INC
  2091                              <1> ; Last Modification: 21/03/2022
  2092                              <1> ; ----------------------------------------------------------------------------
  2093                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2094                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2095                              <1> ;
  2096                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2097                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2098                              <1> ; <Bell Laboratories (17/3/1972)>
  2099                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2100                              <1> ;
  2101                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2102                              <1> ;
  2103                              <1> ; ****************************************************************************
  2104                              <1> 
  2105                              <1> sys_init:
  2106                              <1> 	; 23/02/2022
  2107                              <1> 	; 08/01/2022
  2108                              <1> 	; 01/01/2022
  2109                              <1> 	; 26/12/2021
  2110                              <1> 	; 27/11/2021
  2111                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 (test) compatibility modification
  2112                              <1> 	; 18/10/2015
  2113                              <1> 	; 28/08/2015
  2114                              <1> 	; 24/08/2015
  2115                              <1> 	; 14/08/2015
  2116                              <1> 	; 24/07/2015 
  2117                              <1> 	; 02/07/2015
  2118                              <1> 	; 01/07/2015
  2119                              <1> 	; 23/06/2015
  2120                              <1> 	; 15/04/2015
  2121                              <1> 	; 13/04/2015
  2122                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2123                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2124                              <1> 	;
  2125                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2126                              <1> 	;
  2127                              <1> 	;; 14/02/2014
  2128                              <1> 	;; 14/07/2013
  2129                              <1> 	;mov	ax, 41
  2130                              <1> 	;mov	[rootdir], ax
  2131                              <1> 	;mov	[u.cdir], ax
  2132                              <1> 	;and	al, 1 ; 15/04/2015
  2133                              <1> 	
  2134                              <1> 	; 27/11/2021
  2135                              <1> 	; 18/04/2021 - Retro UNIX 386 v2
  2136 000032AD 31C0                <1> 	xor	eax, eax
  2137 000032AF FEC0                <1> 	inc	al	; eax = 1 (root directory inode) ; runix v2 fs
  2138 000032B1 A3[94750000]        <1> 	mov	[rootdir], eax ; = 1 ; 28/10/2021 (32 bit)
  2139 000032B6 A3[B0750000]        <1> 	mov	[u.cdir], eax ; 28/10/2021 (32 bit)
  2140                              <1> 
  2141 000032BB A2[FD750000]        <1> 	mov	[u.uno], al ; = 1
  2142                              <1> 	;mov	[mpid], ax ; 1 
  2143                              <1> 	;mov	[p.pid], ax ; 1
  2144                              <1> 	; 01/01/2022
  2145 000032C0 A2[92750000]        <1> 	mov	[mpid], al
  2146 000032C5 A2[98710000]        <1> 	mov	[p.pid], al
  2147 000032CA A2[F8710000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2148                              <1> 	;
  2149 000032CF B004                <1> 	mov	al, time_count ; 30/08/2013
  2150 000032D1 A2[F4750000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2151                              <1> 	; 02/07/2015
  2152 000032D6 A1[98700000]        <1> 	mov	eax, [k_page_dir]
  2153 000032DB A3[0C760000]        <1> 	mov	[u.pgdir], eax ; reset
  2154                              <1> 	; 18/10/2015
  2155                              <1> 	;sub	eax, eax
  2156                              <1> 	;mov	[u.ppgdir], eax ; 0
  2157                              <1>         ;
  2158                              <1>  	; 23/02/2022
  2159                              <1>  	;call	epoch
  2160                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2161                              <1> 	; 17/07/2013
  2162 000032E0 E88F060000          <1> 	call 	bf_init ; buffer initialization
  2163                              <1> 	; 23/02/2022
  2164                              <1> 	; (save sysinit time on sb0)
  2165 000032E5 E829030000          <1> 	call	epoch
  2166 000032EA A3[50780000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2167                              <1> 	; 23/06/2015
  2168 000032EF E8C0FAFFFF          <1> 	call	allocate_page
  2169                              <1> 	;;jc	error
  2170                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2171                              <1> 	; 05/12/2021
  2172 000032F4 7305                <1> 	jnc	short sysinit_1
  2173 000032F6 E989000000          <1> 	jmp	panic
  2174                              <1> sysinit_1:
  2175 000032FB A3[08760000]        <1> 	mov	[u.upage], eax ; user structure page	
  2176 00003300 A3[08720000]        <1> 	mov	[p.upage], eax
  2177                              <1> 	;
  2178 00003305 E81BFBFFFF          <1> 	call	clear_page
  2179                              <1> 	;
  2180                              <1> 	; 14/08/2015
  2181 0000330A FA                  <1> 	cli
  2182                              <1> 	; 14/03/2015
  2183                              <1> 	; 17/01/2014
  2184 0000330B E8D0010000          <1> 	call	sp_init ; serial port initialization
  2185                              <1> 	; 14/08/2015
  2186 00003310 FB                  <1> 	sti
  2187                              <1> 	;
  2188                              <1> 	; 30/06/2015
  2189                              <1> 	;mov	esi, kernel_init_ok_msg
  2190                              <1> 	;call 	print_msg
  2191                              <1> 	;
  2192 00003311 30DB                <1> 	xor	bl, bl ; video page 0
  2193                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2194 00003313 E8A8330000          <1> 	call 	vp_clr  ; 17/07/2013
  2195 00003318 FEC3                <1> 	inc	bl
  2196 0000331A 80FB08              <1> 	cmp	bl, 8
  2197 0000331D 72F4                <1> 	jb	short vp_clr_nxt
  2198                              <1> 	;
  2199                              <1> 	; 24/07/2015
  2200                              <1> 	;push	KDATA
  2201                              <1>         ;push	esp
  2202                              <1> 	;mov	[tss.esp0], esp
  2203                              <1>         ;mov	word [tss.ss0], KDATA
  2204                              <1> 	;
  2205                              <1> 	; 08/01/2022
  2206                              <1> 	; 24/08/2015
  2207                              <1> 	;; temporary (01/07/2015)
  2208                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2209                              <1> 	;		       ; it is not needed here !
  2210                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2211 0000331F FE0D[A2750000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2212                              <1> 			      ; 0 = executing a system call
  2213                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2214                              <1> 	;
  2215                              <1> 	;;; 06/08/2015
  2216                              <1> 	;;;call	getch ; wait for a key stroke
  2217                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2218                              <1> ;;sys_init_msg_wait:
  2219                              <1> ;;	push 	ecx
  2220                              <1> ;;	mov	al, 1
  2221                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2222                              <1> ;;	call	getc_n
  2223                              <1> ;;	pop	ecx
  2224                              <1> ;;	jnz	short sys_init_msg_ok
  2225                              <1> ;;	loop	sys_init_msg_wait
  2226                              <1> 	;
  2227                              <1> ;;sys_init_msg_ok:
  2228                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2229 00003325 6A10                <1> 	push	KDATA ; ss
  2230 00003327 54                  <1> 	push	esp
  2231 00003328 9C                  <1> 	pushfd
  2232 00003329 6A08                <1> 	push	KCODE ; cs
  2233 0000332B 68[58330000]        <1> 	push	init_exec ; eip
  2234 00003330 8925[A4750000]      <1> 	mov	[u.sp], esp
  2235 00003336 1E                  <1> 	push	ds
  2236 00003337 06                  <1> 	push	es
  2237 00003338 0FA0                <1> 	push	fs
  2238 0000333A 0FA8                <1> 	push	gs	
  2239 0000333C 60                  <1> 	pushad
  2240 0000333D 8925[A8750000]      <1> 	mov	[u.usp], esp
  2241 00003343 E8CF1C0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2242                              <1> 		      ; and interrupt return components (for IRET)
  2243 00003348 61                  <1> 	popad
  2244 00003349 6658                <1> 	pop	ax ; gs
  2245 0000334B 6658                <1> 	pop	ax ; fs
  2246 0000334D 6658                <1> 	pop	ax ; es
  2247 0000334F 6658                <1> 	pop	ax ; ds	
  2248 00003351 58                  <1> 	pop	eax ; eip (init_exec)
  2249 00003352 6658                <1> 	pop	ax ; cs (KCODE)
  2250 00003354 58                  <1> 	pop	eax ; E-FLAGS
  2251 00003355 58                  <1> 	pop	eax ; esp
  2252 00003356 6658                <1> 	pop	ax ; ss (KDATA)
  2253                              <1> 	;
  2254                              <1> 	; 26/12/2021 ([u.ppgdir] is zero already)
  2255                              <1> 	;xor	eax, eax ; 0
  2256                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2257                              <1> 	;
  2258                              <1> 	; 02/07/2015
  2259                              <1> 	; [u.pgdir ] = [k_page_dir]
  2260                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2261                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2262                              <1> init_exec:
  2263                              <1> 	; 13/03/2013
  2264                              <1> 	; 24/07/2013
  2265 00003358 BB[7A330000]        <1> 	mov	ebx, init_file
  2266 0000335D B9[72330000]        <1> 	mov	ecx, init_argp
  2267                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2268                              <1> 	; ECX contains address of argument list pointer
  2269                              <1> 	;
  2270                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2271                              <1> 			      ; 0 = executing a system call
  2272                              <1> 	sys	_exec  ; execute file
  2282                              <2> 
  2283                              <2> 
  2284 00003362 B80B000000          <2>  mov eax, %1
  2285                              <2>  %if %0 >= 2
  2286                              <2>  mov ebx, %2
  2287                              <2>  %if %0 >= 3
  2288                              <2>  mov ecx, %3
  2289                              <2>  %if %0 = 4
  2290                              <2>  mov edx, %4
  2291                              <2>  %endif
  2292                              <2>  %endif
  2293                              <2>  %endif
  2294 00003367 CD30                <2>  int 30h
  2273 00003369 7319                <1> 	jnc	short panic
  2274                              <1> 	;
  2275 0000336B BE[AC6D0000]        <1> 	mov	esi, etc_init_err_msg
  2276                              <1> 	; 22/11/2021
  2277                              <1> 	;call 	print_msg
  2278 00003370 EB17                <1> 	jmp	short key_to_reboot
  2279                              <1> 
  2280                              <1> ;align 4
  2281                              <1> init_argp:
  2282 00003372 [7A330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2283                              <1> init_file:
  2284                              <1> 	; 24/08/2015
  2285 0000337A 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2285 00003383 00                  <1>
  2286                              <1> panic:
  2287                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2288                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2289 00003384 BE[916D0000]        <1> 	mov 	esi, panic_msg
  2290                              <1> key_to_reboot: ; 22/11/2021
  2291 00003389 E819000000          <1> 	call 	print_msg
  2292                              <1> ;key_to_reboot:
  2293                              <1> 	; 15/11/2015
  2294 0000338E E87B310000          <1> 	call 	getch 
  2295                              <1> 		; wait for a character from the current tty
  2296                              <1> 	;
  2297 00003393 B00A                <1> 	mov	al, 0Ah
  2298 00003395 8A1D[C6700000]      <1> 	mov	bl, [ptty] ; [active_page]
  2299 0000339B B407                <1> 	mov	ah, 07h ; Black background, 
  2300                              <1> 			; light gray forecolor
  2301 0000339D E822E0FFFF          <1> 	call 	write_tty
  2302 000033A2 E9BDDCFFFF          <1> 	jmp	cpu_reset 
  2303                              <1> 
  2304                              <1> print_msg:
  2305                              <1> 	; 01/07/2015
  2306                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2307                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2308                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2309                              <1> 	;
  2310                              <1> 	;
  2311 000033A7 AC                  <1> 	lodsb
  2312                              <1> pmsg1:
  2313 000033A8 56                  <1> 	push 	esi
  2314 000033A9 0FB61D[C6700000]    <1> 	movzx	ebx, byte [ptty]
  2315 000033B0 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2316 000033B2 E80DE0FFFF          <1> 	call 	write_tty
  2317 000033B7 5E                  <1> 	pop	esi
  2318 000033B8 AC                  <1> 	lodsb
  2319 000033B9 20C0                <1> 	and 	al, al
  2320 000033BB 75EB                <1> 	jnz 	short pmsg1
  2321 000033BD C3                  <1> 	retn
  2322                              <1> 	
  2323                              <1> ctrlbrk:
  2324                              <1> 	; 06/02/2022
  2325                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2326                              <1> 	; 12/11/2015
  2327                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2328                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2329                              <1> 	;
  2330                              <1> 	; INT 1Bh (control+break) handler		
  2331                              <1> 	;
  2332                              <1>       	; Retro Unix 8086 v1 feature only!
  2333                              <1>       	;
  2334 000033BE 66833D[F8750000]00  <1> 	cmp 	word [u.intr], 0
  2335 000033C6 764B                <1> 	jna 	short cbrk4
  2336                              <1> cbrk0:
  2337                              <1> 	; 12/11/2015
  2338                              <1> 	; 06/12/2013
  2339 000033C8 66833D[FA750000]00  <1> 	cmp 	word [u.quit], 0
  2340 000033D0 7441                <1> 	jz	short cbrk4
  2341                              <1> 	;
  2342                              <1> 	; 20/09/2013	
  2343                              <1> 	;push 	ax
  2344                              <1> 	; 04/12/2021
  2345 000033D2 50                  <1> 	push	eax
  2346                              <1> 
  2347                              <1> 	; 06/02/2022
  2348                              <1> 	; (repetitive ctrl+brk check) 
  2349 000033D3 66A1[FA750000]      <1> 	mov	ax, [u.quit]
  2350 000033D9 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2351 000033DB 7435                <1> 	jz	short cbrk3
  2352                              <1> 
  2353                              <1> 	; 06/12/2013
  2354 000033DD A0[C6700000]        <1> 	mov	al, [ptty]
  2355                              <1> 	;
  2356                              <1> 	; 12/11/2015
  2357                              <1> 	;
  2358                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2359                              <1> 	; or ctrl+break from console (pseudo) tty
  2360                              <1> 	; (!redirection!)
  2361                              <1> 	;
  2362 000033E2 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2363 000033E4 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2364                              <1> 	;	
  2365                              <1> 	; Serial port interrupt handler sets [ptty]
  2366                              <1> 	; to the port's tty number (as temporary).
  2367                              <1> 	;
  2368                              <1> 	; If active process is using a stdin or 
  2369                              <1> 	; stdout redirection (by the shell),
  2370                              <1>         ; console tty keyboard must be available
  2371                              <1> 	; to terminate running process,
  2372                              <1> 	; in order to prevent a deadlock. 
  2373                              <1> 	;
  2374 000033E6 52                  <1> 	push	edx
  2375 000033E7 0FB615[FD750000]    <1> 	movzx	edx, byte [u.uno]
  2376 000033EE 3A82[D7710000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2377 000033F4 5A                  <1> 	pop	edx
  2378 000033F5 7412                <1> 	je	short cbrk2
  2379                              <1> cbrk1:
  2380 000033F7 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2381                              <1> 	; 06/12/2013
  2382 000033F9 3A05[E2750000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2383 000033FF 7408                <1> 	je	short cbrk2	
  2384 00003401 3A05[E3750000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2385 00003407 7509                <1> 	jne	short cbrk3	
  2386                              <1> cbrk2:
  2387                              <1> 	;; 06/12/2013
  2388                              <1> 	;mov	ax, [u.quit]
  2389                              <1> 	;and	ax, ax
  2390                              <1> 	;jz	short cbrk3
  2391                              <1> 	;
  2392                              <1> 	;xor	ax, ax ; 0
  2393                              <1> 	;dec	ax
  2394                              <1> 	; 04/12/2021
  2395 00003409 31C0                <1> 	xor	eax, eax ; 0
  2396 0000340B 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2397                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2398 0000340C 66A3[FA750000]      <1> 	mov	[u.quit], ax
  2399                              <1> cbrk3:
  2400                              <1> 	;pop	ax
  2401                              <1> 	; 04/12/2021
  2402 00003412 58                  <1> 	pop	eax
  2403                              <1> cbrk4:
  2404 00003413 C3                  <1> 	retn
  2405                              <1> 
  2406                              <1> com2_int:
  2407                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2408                              <1> 	; 07/11/2015 
  2409                              <1> 	; 24/10/2015
  2410                              <1> 	; 23/10/2015
  2411                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2412                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2413                              <1> 	; < serial port 2 interrupt handler >
  2414                              <1> 	;
  2415 00003414 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2416                              <1> 	;;push	eax
  2417                              <1> 	; 08/01/2022
  2418 00003417 29C0                <1> 	sub	eax, eax
  2419 00003419 B009                <1> 	mov	al, 9
  2420                              <1> 	;mov	ax, 9
  2421 0000341B EB07                <1> 	jmp	short comm_int
  2422                              <1> com1_int:
  2423                              <1> 	; 07/11/2015
  2424                              <1> 	; 24/10/2015
  2425 0000341D 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2426                              <1> 	; 23/10/2015
  2427                              <1> 	;push	eax
  2428                              <1> 	; 08/01/2022
  2429 00003420 29C0                <1> 	sub	eax, eax
  2430 00003422 B008                <1> 	mov	al, 8
  2431                              <1> 	;mov	ax, 8
  2432                              <1> comm_int:
  2433                              <1> 	; 08/01/2022
  2434                              <1> 	; 20/11/2015
  2435                              <1> 	; 18/11/2015
  2436                              <1> 	; 17/11/2015
  2437                              <1> 	; 16/11/2015
  2438                              <1> 	; 09/11/2015
  2439                              <1> 	; 08/11/2015
  2440                              <1> 	; 07/11/2015
  2441                              <1> 	; 06/11/2015 (serial4.asm, 'serial')	
  2442                              <1> 	; 01/11/2015
  2443                              <1> 	; 26/10/2015
  2444                              <1> 	; 23/10/2015
  2445 00003424 53                  <1> 	push	ebx
  2446 00003425 56                  <1> 	push	esi
  2447 00003426 57                  <1> 	push	edi
  2448 00003427 1E                  <1> 	push 	ds
  2449 00003428 06                  <1> 	push 	es
  2450                              <1> 	; 18/11/2015
  2451 00003429 0F20DB              <1> 	mov	ebx, cr3
  2452 0000342C 53                  <1> 	push	ebx ; ****
  2453                              <1> 	;
  2454 0000342D 51                  <1> 	push	ecx ; ***
  2455 0000342E 52                  <1> 	push	edx ; **
  2456                              <1> 	;
  2457 0000342F BB10000000          <1> 	mov	ebx, KDATA
  2458 00003434 8EDB                <1> 	mov	ds, bx
  2459 00003436 8EC3                <1> 	mov	es, bx
  2460                              <1> 	;
  2461 00003438 8B0D[98700000]      <1> 	mov	ecx, [k_page_dir]
  2462 0000343E 0F22D9              <1> 	mov	cr3, ecx
  2463                              <1> 	; 20/11/2015
  2464                              <1> 	; Interrupt identification register
  2465 00003441 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2466                              <1> 	;
  2467 00003445 3C08                <1> 	cmp 	al, 8 
  2468 00003447 7702                <1> 	ja 	short com_i0
  2469                              <1> 	;
  2470                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2471                              <1> 	; 20/11/2015
  2472                              <1> 	; 17/11/2015
  2473                              <1> 	; 16/11/2015
  2474                              <1> 	; 15/11/2015
  2475                              <1> 	; 24/10/2015
  2476                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2477                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2478                              <1> 	; < serial port 1 interrupt handler >
  2479                              <1> 	;
  2480 00003449 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2481                              <1> com_i0:
  2482                              <1> 	;push	eax ; *
  2483                              <1> 	; 07/11/2015
  2484 0000344B A2[06710000]        <1> 	mov 	byte [ccomport], al
  2485                              <1> 	; 09/11/2015
  2486                              <1> 	;movzx	ebx, ax ; 8 or 9
  2487                              <1> 	; 08/01/2022
  2488 00003450 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2489                              <1> 	; 17/11/2015
  2490                              <1>  	; reset request for response status
  2491 00003452 88A3[FC700000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2492                              <1> 	;
  2493                              <1> 	; 20/11/2015
  2494 00003458 EC                  <1> 	in	al, dx		; read interrupt id. register
  2495 00003459 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2496 0000345B 2404                <1> 	and	al, 4		; received data available?	
  2497 0000345D 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2498                              <1> 	;
  2499                              <1> 	; 20/11/2015
  2500 0000345F 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2501 00003462 EC                  <1> 	in	al, dx     	; read character
  2502                              <1> 	;JMP	$+2	   	; I/O DELAY
  2503                              <1> 	; 08/11/2015
  2504                              <1> 	; 07/11/2015
  2505 00003463 89DE                <1> 	mov	esi, ebx 
  2506 00003465 89DF                <1> 	mov	edi, ebx
  2507 00003467 81C6[00710000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2508 0000346D 81C7[02710000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2509 00003473 8806                <1> 	mov	[esi], al ; received char (current char)
  2510                              <1> 	; query
  2511 00003475 20C0                <1> 	and	al, al
  2512 00003477 7527                <1> 	jnz	short com_i2
  2513                              <1>    	; response
  2514                              <1> 	; 17/11/2015
  2515                              <1> 	; set request for response status
  2516 00003479 FE83[FC700000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2517                              <1> 	;
  2518 0000347F 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2519 00003483 EC                  <1> 	in	al, dx	   	; read line status register 
  2520 00003484 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2521 00003486 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2522 00003488 7445                <1> 	jz	short com_eoi 	; no
  2523 0000348A B0FF                <1> 	mov 	al, 0FFh   	; response			
  2524 0000348C 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2525 00003490 EE                  <1> 	out	dx, al	   	; send on serial port
  2526                              <1> 	; 17/11/2015
  2527 00003491 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2528 00003494 7502                <1> 	jne 	short com_i1    ; no
  2529 00003496 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2530                              <1> com_i1:
  2531                              <1> 	; 17/11/2015
  2532                              <1> 	; reset request for response status (again)
  2533 00003498 FE8B[FC700000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2534 0000349E EB2F                <1> 	jmp	short com_eoi
  2535                              <1> com_i2:	
  2536                              <1> 	; 08/11/2015
  2537 000034A0 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2538 000034A2 7417                <1> 	je	short com_i3	; (check for response signal)
  2539                              <1> 	; 07/11/2015
  2540 000034A4 3C04                <1> 	cmp	al, 04h	; EOT
  2541 000034A6 751C                <1> 	jne	short com_i4	
  2542                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2543                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2544                              <1> 	; 08/11/2015
  2545                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2546 000034A8 861D[C6700000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2547 000034AE E80BFFFFFF          <1> 	call 	ctrlbrk
  2548 000034B3 861D[C6700000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2549                              <1> 	;mov	al, 04h ; EOT
  2550                              <1> 	; 08/11/2015
  2551 000034B9 EB09                <1> 	jmp	short com_i4	
  2552                              <1> com_i3:
  2553                              <1> 	; 08/11/2015
  2554                              <1> 	; If 0FFh has been received just after a query
  2555                              <1> 	; (schar, ZERO), it is a response signal.
  2556                              <1> 	; 17/11/2015
  2557 000034BB 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2558 000034BE 7704                <1> 	ja	short com_i4 ; no
  2559                              <1> 	; reset query status (schar)
  2560 000034C0 8807                <1> 	mov	[edi], al ; 0FFh
  2561 000034C2 FEC0                <1> 	inc	al ; 0
  2562                              <1> com_i4:
  2563                              <1> 	; 27/07/2014
  2564                              <1> 	; 09/07/2014
  2565 000034C4 D0E3                <1> 	shl	bl, 1	
  2566 000034C6 81C3[C8700000]      <1> 	add	ebx, ttychr
  2567                              <1> 	; 23/07/2014 (always overwrite)
  2568                              <1> 	;;cmp	word [ebx], 0
  2569                              <1> 	;;ja	short com_eoi
  2570                              <1> 	;
  2571 000034CC 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2572                              <1> 			    ; scan code = 0
  2573                              <1> com_eoi:
  2574                              <1> 	;mov	al, 20h
  2575                              <1> 	;out	20h, al	   ; end of interrupt
  2576                              <1> 	;
  2577                              <1> 	; 07/11/2015
  2578                              <1>       	;pop	eax ; *
  2579 000034CF A0[06710000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2580                              <1> 	; al = tty number (8 or 9)
  2581 000034D4 E8181C0000          <1>         call	wakeup
  2582                              <1> com_iret:
  2583                              <1> 	; 23/10/2015
  2584 000034D9 5A                  <1> 	pop	edx ; **
  2585 000034DA 59                  <1> 	pop	ecx ; ***
  2586                              <1> 	; 18/11/2015
  2587                              <1> 	;pop	eax ; ****
  2588                              <1> 	;mov	cr3, eax
  2589                              <1> 	;jmp	iiret
  2590 000034DB E9C2D4FFFF          <1> 	jmp	iiretp
  2591                              <1> 
  2592                              <1> ;iiretp: ; 01/09/2015
  2593                              <1> ;	; 28/08/2015
  2594                              <1> ;	pop	eax ; (*) page directory
  2595                              <1> ;	mov	cr3, eax
  2596                              <1> ;iiret:
  2597                              <1> ;	; 22/08/2014
  2598                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2599                              <1> ;	out	20h, al	; 8259 PORT
  2600                              <1> ;	;
  2601                              <1> ;	pop	es
  2602                              <1> ;	pop	ds
  2603                              <1> ;	pop	edi
  2604                              <1> ;	pop	esi
  2605                              <1> ;	pop	ebx ; 29/08/2014
  2606                              <1> ;	pop 	eax
  2607                              <1> ;	iretd
  2608                              <1> 
  2609                              <1> sp_init:
  2610                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2611                              <1> 	; 07/11/2015
  2612                              <1> 	; 29/10/2015
  2613                              <1> 	; 26/10/2015
  2614                              <1> 	; 23/10/2015
  2615                              <1> 	; 29/06/2015
  2616                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2617                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2618                              <1> 	; Initialization of Serial Port Communication Parameters
  2619                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2620                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2621                              <1> 	;
  2622                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2623                              <1> 	;
  2624                              <1> 	; INPUT:  (29/06/2015)
  2625                              <1> 	;	AL = 0 for COM1
  2626                              <1> 	;	     1 for COM2
  2627                              <1> 	;	AH = Communication parameters	
  2628                              <1> 	;
  2629                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2630                              <1> 	;	Bit	4	3	2	1	0
  2631                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2632                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2633                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2634                              <1> 	;		11 = even
  2635                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2636                              <1> 	;		Retro UNIX 386 v1 feature only !
  2637                              <1> 	;	Bit	7    6    5  | Baud rate
  2638                              <1> 	;		------------------------
  2639                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2640                              <1> 	;		0    0    1  | 9600 (12)
  2641                              <1> 	;		0    1    0  | 19200 (6) 
  2642                              <1> 	;		0    1	  1  | 38400 (3) 
  2643                              <1> 	;		1    0	  0  | 14400 (8)
  2644                              <1> 	;		1    0	  1  | 28800 (4)
  2645                              <1> 	;		1    1    0  | 57600 (2)
  2646                              <1> 	;		1    1    1  | 115200 (1) 	
  2647                              <1> 	
  2648                              <1> 	; References:	
  2649                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2650                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2651                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2652                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2653                              <1> 	;
  2654                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2655                              <1> 	;
  2656 000034E0 BB[02710000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2657 000034E5 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2658                              <1> 	; 29/10/2015
  2659 000034E9 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2660 000034ED E84F000000          <1> 	call	sp_i3	; call A4	
  2661 000034F2 A880                <1> 	test	al, 80h
  2662 000034F4 740E                <1> 	jz	short sp_i0 ; OK..
  2663                              <1> 		; Error !
  2664                              <1> 	;mov	dx, 3F8h
  2665 000034F6 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2666                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2667                              <1> 	; 08/01/2022
  2668 000034F9 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2669 000034FB E841000000          <1> 	call	sp_i3	; call A4	
  2670 00003500 A880                <1> 	test	al, 80h
  2671 00003502 7508                <1> 	jnz	short sp_i1
  2672                              <1> sp_i0:
  2673                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2674                              <1>         ; (INT 14h initialization code disables interrupts.)
  2675                              <1> 	;
  2676 00003504 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2677 00003507 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2678                              <1> sp_i1:
  2679 0000350C 43                  <1> 	inc	ebx
  2680 0000350D 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2681                              <1> 	; 29/10/2015
  2682                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2683                              <1> 	; 08/01/2022
  2684 00003511 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2685 00003513 E829000000          <1> 	call	sp_i3	; call A4	
  2686 00003518 A880                <1> 	test	al, 80h
  2687 0000351A 740E                <1> 	jz	short sp_i2 ; OK..
  2688                              <1> 		; Error !
  2689                              <1> 	;mov	dx, 2F8h
  2690 0000351C 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2691                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2692                              <1> 	; 08/01/2022
  2693 0000351F B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2694 00003521 E81B000000          <1> 	call	sp_i3	; call A4	
  2695 00003526 A880                <1> 	test	al, 80h
  2696 00003528 7516                <1> 	jnz	short sp_i7
  2697                              <1> sp_i2:
  2698 0000352A C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2699                              <1> sp_i6:
  2700                              <1> 	;; COM2 - enabling IRQ 3
  2701                              <1> 	; 08/01/2022
  2702 0000352D B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2703                              <1> 	; 07/11/2015
  2704                              <1> 	; 26/10/2015
  2705                              <1> 	;pushf
  2706                              <1> 	;cli
  2707                              <1> 	;;
  2708                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2709                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2710                              <1> 	;in	al, dx 	   		; read register
  2711                              <1> 	;JMP	$+2	   		; I/O DELAY
  2712                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2713                              <1> 	;out	dx, al     		; write back to register
  2714                              <1> 	;JMP	$+2	   		; I/O DELAY
  2715                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2716                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2717                              <1> 	;in	al, dx     		; read register
  2718                              <1> 	;JMP	$+2	   		; I/O DELAY
  2719                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2720                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2721                              <1> 	;out	dx, al 	   		; write back to register
  2722                              <1> 	;JMP	$+2        		; I/O DELAY
  2723                              <1> 	;in	al, 21h    		; read interrupt mask register
  2724                              <1> 	;JMP	$+2	   		; I/O DELAY
  2725                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2726                              <1> 	;out	21h, al    		; write back to register
  2727                              <1> 	;
  2728                              <1> 	; 08/01/2022
  2729 0000352F 9C                  <1> 	pushf
  2730 00003530 E8AA000000          <1> 	call	sp_i8
  2731                              <1> 	; 23/10/2015
  2732 00003535 B8[14340000]        <1> 	mov 	eax, com2_int
  2733 0000353A A3[3F3A0000]        <1> 	mov	[com2_irq3], eax
  2734                              <1> 	; 26/10/2015
  2735 0000353F 9D                  <1> 	popf	
  2736                              <1> sp_i7:
  2737 00003540 C3                  <1> 	retn
  2738                              <1> 
  2739                              <1> sp_i3:
  2740                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2741                              <1> 	; 28/10/2015
  2742 00003541 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2743 00003543 B000                <1> 	mov	al, 0
  2744 00003545 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2745 00003546 EB00                <1> 	JMP	$+2			; I/O DELAY
  2746 00003548 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2747 0000354B B080                <1> 	mov	al, 80h			
  2748 0000354D EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2749                              <1> 	;-----	SET BAUD RATE DIVISOR
  2750                              <1> 	; 26/10/2015
  2751 0000354E 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2752                              <1> 					; of the divisor value
  2753 00003551 88C8                <1> 	mov	al, cl	; 1
  2754 00003553 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2755                              <1> 					; 2 = 57600 baud
  2756                              <1> 					; 3 = 38400 baud
  2757                              <1> 					; 6 = 19200 baud
  2758                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2759 00003554 EB00                <1> 	JMP	$+2			; I/O DELAY
  2760 00003556 28C0                <1> 	sub	al, al
  2761 00003558 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2762                              <1> 					; of the divisor value
  2763 0000355A EE                  <1> 	out	dx, al ; 0
  2764 0000355B EB00                <1> 	JMP	$+2			; I/O DELAY
  2765                              <1> 	;	
  2766 0000355D 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2767                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2768 0000355F 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2769 00003562 EE                  <1> 	out	dx, al			
  2770 00003563 EB00                <1> 	JMP	$+2			; I/O DELAY
  2771                              <1> 	; 29/10/2015
  2772 00003565 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2773 00003567 30C0                <1> 	xor	al, al			; 0
  2774 00003569 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2775 0000356A EB00                <1> 	JMP	$+2	
  2776                              <1> sp_i4:
  2777                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2778                              <1> 	; 29/06/2015 (line status after modem status)
  2779 0000356C 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2780                              <1> sp_i4s:
  2781 0000356F EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2782 00003570 EB00                <1> 	JMP	$+2			; I/O DELAY
  2783 00003572 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2784 00003574 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2785                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2786 00003576 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2787                              <1> 	; AL = Line status, AH = Modem status
  2788 00003577 C3                  <1> 	retn
  2789                              <1> 
  2790                              <1> sp_status:
  2791                              <1> 	; 29/06/2015
  2792                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2793                              <1> 	; Get serial port status
  2794 00003578 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2795 0000357C 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2796                              <1> 					; dx = 2FEh for COM2
  2797 0000357E EBEF                <1> 	jmp	short sp_i4s
  2798                              <1> 
  2799                              <1> sp_setp: ; Set serial port communication parameters
  2800                              <1> 	; 08/01/2022
  2801                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2802                              <1> 	; 07/11/2015
  2803                              <1> 	; 29/10/2015
  2804                              <1> 	; 29/06/2015
  2805                              <1> 	; Retro UNIX 386 v1 feature only !	
  2806                              <1> 	;
  2807                              <1> 	; INPUT:
  2808                              <1> 	;	AL = 0 for COM1
  2809                              <1> 	;	     1 for COM2
  2810                              <1> 	;	AH = Communication parameters (*)
  2811                              <1> 	; OUTPUT:
  2812                              <1> 	;	CL = Line status
  2813                              <1> 	;	CH = Modem status
  2814                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2815                              <1> 	;		 'invalid parameter !' 
  2816                              <1> 	;		 	 or
  2817                              <1> 	;		 'device not ready !' error
  2818                              <1> 	;	
  2819                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2820                              <1> 	;	Bit	4	3	2	1	0
  2821                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2822                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2823                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2824                              <1> 	;		11 = even
  2825                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2826                              <1> 	;		Retro UNIX 386 v1 feature only !
  2827                              <1> 	;	Bit	7    6    5  | Baud rate
  2828                              <1> 	;		------------------------
  2829                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2830                              <1> 	;		0    0    1  | 9600 (12)
  2831                              <1> 	;		0    1    0  | 19200 (6) 
  2832                              <1> 	;		0    1	  1  | 38400 (3) 
  2833                              <1> 	;		1    0	  0  | 14400 (8)
  2834                              <1> 	;		1    0	  1  | 28800 (4)
  2835                              <1> 	;		1    1    0  | 57600 (2)
  2836                              <1> 	;		1    1    1  | 115200 (1) 
  2837                              <1> 	;
  2838                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2839                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2840                              <1> 	;
  2841                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2842                              <1> 	;
  2843 00003580 66BAF803            <1> 	mov	dx, 3F8h
  2844 00003584 BB[02710000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2845 00003589 3C01                <1> 	cmp	al, 1
  2846 0000358B 7770                <1> 	ja 	short sp_invp_err
  2847 0000358D 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2848 0000358F FECE                <1> 	dec	dh ; 2F8h
  2849 00003591 43                  <1> 	inc	ebx ; COM2 control byte offset
  2850                              <1> sp_setp1:
  2851                              <1> 	; 29/10/2015
  2852 00003592 8823                <1> 	mov	[ebx], ah
  2853 00003594 0FB6CC              <1> 	movzx 	ecx, ah
  2854 00003597 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2855 0000359A 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2856 0000359D 8A81[0C360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2857 000035A3 6689C1              <1> 	mov	cx, ax
  2858 000035A6 E896FFFFFF          <1> 	call	sp_i3
  2859 000035AB 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2860 000035AE A880                <1> 	test	al, 80h
  2861 000035B0 740F                <1> 	jz	short sp_setp2
  2862 000035B2 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2863                              <1> stp_dnr_err:
  2864 000035B5 C705[20760000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2864 000035BD 0000                <1>
  2865                              <1> 	; CL = Line status, CH = Modem status
  2866 000035BF F9                  <1> 	stc
  2867 000035C0 C3                  <1> 	retn
  2868                              <1> sp_setp2:
  2869 000035C1 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2870                              <1>         ;jna	sp_i6
  2871                              <1> 		      ; COM1 (3F?h)
  2872                              <1> 	; 24/12/2021
  2873 000035C4 7705                <1> 	ja	short sp_i5
  2874 000035C6 E962FFFFFF          <1> 	jmp	sp_i6
  2875                              <1> sp_i5: 
  2876                              <1> 	; 08/01/2022
  2877 000035CB B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2878                              <1> 	; 07/11/2015
  2879                              <1> 	; 26/10/2015
  2880                              <1> 	; 29/06/2015
  2881                              <1> 	;
  2882                              <1> 	;; COM1 - enabling IRQ 4
  2883                              <1> 	;pushf
  2884                              <1> 	;cli
  2885                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2886                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2887                              <1> 	;in	al, dx 	   		; read register
  2888                              <1> 	;JMP	$+2			; I/O DELAY
  2889                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2890                              <1> 	;out	dx, al     		; write back to register
  2891                              <1> 	;JMP	$+2			; I/O DELAY
  2892                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2893                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2894                              <1> 	;in	al, dx     		; read register
  2895                              <1> 	;JMP	$+2			; I/O DELAY
  2896                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2897                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2898                              <1> 	;out	dx, al 	   		; write back to register
  2899                              <1> 	;JMP	$+2        		; I/O DELAY
  2900                              <1> 	;in	al, 21h    		; read interrupt mask register
  2901                              <1> 	;JMP	$+2			; I/O DELAY
  2902                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2903                              <1> 	;out	21h, al    		; write back to register
  2904                              <1> 	;
  2905                              <1> 	; 08/01/2022
  2906 000035CD 9C                  <1> 	pushf
  2907 000035CE E80C000000          <1> 	call	sp_i8
  2908                              <1> 	; 23/10/2015
  2909 000035D3 B8[1D340000]        <1> 	mov 	eax, com1_int
  2910 000035D8 A3[3B3A0000]        <1> 	mov	[com1_irq4], eax
  2911                              <1> 	; 26/10/2015
  2912 000035DD 9D                  <1> 	popf
  2913 000035DE C3                  <1> 	retn
  2914                              <1> 
  2915                              <1> sp_i8:
  2916                              <1> 	; 08/01/2022
  2917                              <1> 	;pushf
  2918 000035DF FA                  <1> 	cli
  2919                              <1> 	;
  2920                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2921 000035E0 B2FC                <1> 	mov	dl, 0FCh
  2922 000035E2 EC                  <1> 	in	al, dx 	   		; read register
  2923 000035E3 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2924 000035E5 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2925 000035E7 EE                  <1> 	out	dx, al     		; write back to register
  2926 000035E8 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2927                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2928 000035EA B2F9                <1> 	mov	dl, 0F9h
  2929 000035EC EC                  <1> 	in	al, dx     		; read register
  2930 000035ED EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2931                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2932 000035EF 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2933 000035F1 EE                  <1> 	out	dx, al 	   		; write back to register
  2934 000035F2 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2935 000035F4 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2936 000035F6 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2937                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2938 000035F8 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2939 000035FA E621                <1> 	out	21h, al    		; write back to register
  2940                              <1> 	;
  2941                              <1> 	;popf	
  2942 000035FC C3                  <1> 	retn
  2943                              <1> 
  2944                              <1> sp_invp_err:
  2945 000035FD C705[20760000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2945 00003605 0000                <1>
  2946 00003607 31C9                <1> 	xor	ecx, ecx
  2947 00003609 49                  <1> 	dec	ecx ; 0FFFFh
  2948 0000360A F9                  <1> 	stc
  2949 0000360B C3                  <1> 	retn
  2950                              <1> 
  2951                              <1> ; 29/10/2015
  2952                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2953 0000360C 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2954                              <1> 
  2955                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2956                              <1> epoch:
  2957                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2958                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2959                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2960                              <1> 	; 'epoch' procedure prototype: 
  2961                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2962                              <1> 	; 14/11/2012
  2963                              <1> 	; unixboot.asm (boot file configuration)
  2964                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2965                              <1> 	; 21/7/2012
  2966                              <1> 	; 15/7/2012
  2967                              <1> 	; 14/7/2012		
  2968                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2969                              <1> 	; compute current date and time as UNIX Epoch/Time
  2970                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2971                              <1> 	;
  2972                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2973                              <1> 	;
  2974 00003613 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2975 00003618 86E9                <1>         xchg 	ch,cl
  2976 0000361A 66890D[066E0000]    <1>         mov 	[hour], cx
  2977 00003621 86F2                <1>         xchg 	dh,dl
  2978 00003623 668915[0A6E0000]    <1>         mov 	[second], dx
  2979                              <1> 	;
  2980 0000362A E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2981 0000362F 86E9                <1>         xchg 	ch,cl
  2982 00003631 66890D[006E0000]    <1>         mov 	[year], cx
  2983 00003638 86F2                <1>         xchg 	dh,dl
  2984 0000363A 668915[026E0000]    <1>         mov 	[month], dx
  2985                              <1> 	;
  2986 00003641 66B93030            <1> 	mov 	cx, 3030h
  2987                              <1> 	;
  2988 00003645 A0[066E0000]        <1> 	mov 	al, [hour] ; Hour
  2989                              <1>         	; AL <= BCD number)
  2990 0000364A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2991                              <1> 					; AH = AL / 10h
  2992                              <1> 					; AL = AL MOD 10h
  2993 0000364C D50A                <1>         aad 	; AX= AH*10+AL
  2994 0000364E A2[066E0000]        <1> 	mov 	[hour], al
  2995 00003653 A0[076E0000]        <1> 	mov 	al, [hour+1] ; Minute
  2996                              <1>         	; AL <= BCD number)
  2997 00003658 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2998                              <1> 					; AH = AL / 10h
  2999                              <1> 					; AL = AL MOD 10h
  3000 0000365A D50A                <1>         aad 	; AX= AH*10+AL
  3001 0000365C A2[086E0000]        <1> 	mov 	[minute], al
  3002 00003661 A0[0A6E0000]        <1> 	mov 	al, [second] ; Second
  3003                              <1>         	; AL <= BCD number)
  3004 00003666 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3005                              <1> 					; AH = AL / 10h
  3006                              <1> 					; AL = AL MOD 10h
  3007 00003668 D50A                <1>         aad 	; AX= AH*10+AL
  3008 0000366A A2[0A6E0000]        <1> 	mov 	[second], al
  3009 0000366F 66A1[006E0000]      <1> 	mov 	ax, [year] ; Year (century)
  3010                              <1> 	;push 	ax
  3011                              <1> 	; 04/12/2021
  3012 00003675 50                  <1> 	push	eax
  3013                              <1> 	   	; AL <= BCD number)
  3014 00003676 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3015                              <1> 					; AH = AL / 10h
  3016                              <1> 					; AL = AL MOD 10h
  3017 00003678 D50A                <1>         aad 	; AX= AH*10+AL
  3018 0000367A B464                <1> 	mov 	ah, 100
  3019 0000367C F6E4                <1> 	mul 	ah
  3020 0000367E 66A3[006E0000]      <1> 	mov 	[year], ax
  3021                              <1> 	;pop	ax
  3022                              <1> 	; 04/12/2021
  3023 00003684 58                  <1> 	pop	eax
  3024 00003685 88E0                <1> 	mov	al, ah
  3025                              <1>         	; AL <= BCD number)
  3026 00003687 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3027                              <1> 					; AH = AL / 10h
  3028                              <1> 					; AL = AL MOD 10h
  3029 00003689 D50A                <1>         aad 	; AX= AH*10+AL
  3030 0000368B 660105[006E0000]    <1> 	add 	[year], ax
  3031 00003692 A0[026E0000]        <1> 	mov 	al, [month] ; Month
  3032                              <1>            	; AL <= BCD number)
  3033 00003697 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3034                              <1> 					; AH = AL / 10h
  3035                              <1> 					; AL = AL MOD 10h
  3036 00003699 D50A                <1>         aad 	; AX= AH*10+AL
  3037 0000369B A2[026E0000]        <1> 	mov 	[month], al	
  3038 000036A0 A0[036E0000]        <1>         mov     al, [month+1]      	; Day
  3039                              <1>            	; AL <= BCD number)
  3040 000036A5 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3041                              <1> 					; AH = AL / 10h
  3042                              <1> 					; AL = AL MOD 10h
  3043 000036A7 D50A                <1>         aad 	; AX= AH*10+AL
  3044 000036A9 A2[046E0000]        <1>         mov     [day], al
  3045                              <1> 	
  3046                              <1> convert_to_epoch:
  3047                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3048                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3049                              <1> 	;
  3050                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3051                              <1> 	;
  3052                              <1> 	; Derived from DALLAS Semiconductor
  3053                              <1> 	; Application Note 31 (DS1602/DS1603)
  3054                              <1> 	; 6 May 1998
  3055 000036AE 29C0                <1> 	sub 	eax, eax
  3056 000036B0 66A1[006E0000]      <1> 	mov 	ax, [year]
  3057 000036B6 662DB207            <1> 	sub 	ax, 1970
  3058 000036BA BA6D010000          <1> 	mov 	edx, 365
  3059 000036BF F7E2                <1> 	mul 	edx
  3060 000036C1 31DB                <1> 	xor 	ebx, ebx
  3061 000036C3 8A1D[026E0000]      <1> 	mov 	bl, [month]
  3062 000036C9 FECB                <1> 	dec 	bl
  3063 000036CB D0E3                <1> 	shl 	bl, 1
  3064                              <1> 	;sub	edx, edx
  3065 000036CD 668B93[0C6E0000]    <1> 	mov 	dx, [EBX+DMonth]
  3066 000036D4 8A1D[046E0000]      <1>         mov     bl, [day]
  3067 000036DA FECB                <1> 	dec 	bl
  3068 000036DC 01D0                <1> 	add 	eax, edx
  3069 000036DE 01D8                <1> 	add 	eax, ebx
  3070                              <1> 			; EAX = days since 1/1/1970
  3071 000036E0 668B15[006E0000]    <1> 	mov 	dx, [year]
  3072 000036E7 6681EAB107          <1> 	sub 	dx, 1969
  3073 000036EC 66D1EA              <1> 	shr 	dx, 1
  3074 000036EF 66D1EA              <1> 	shr 	dx, 1		
  3075                              <1> 		; (year-1969)/4
  3076 000036F2 01D0                <1> 	add 	eax, edx
  3077                              <1> 			; + leap days since 1/1/1970
  3078 000036F4 803D[026E0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3079 000036FB 7610                <1> 	jna 	short cte1
  3080 000036FD 668B15[006E0000]    <1> 	mov 	dx, [year]
  3081 00003704 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3082 00003708 7503                <1> 	jnz 	short cte1		
  3083                              <1> 			; and if leap year
  3084 0000370A 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3085                              <1> cte1: 			; compute seconds since 1/1/1970
  3086 0000370D BA18000000          <1> 	mov 	edx, 24
  3087 00003712 F7E2                <1> 	mul	edx
  3088 00003714 8A15[066E0000]      <1> 	mov 	dl, [hour]
  3089 0000371A 01D0                <1> 	add 	eax, edx
  3090                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3091                              <1> 	;mov	ebx, 60
  3092 0000371C B33C                <1> 	mov	bl, 60
  3093 0000371E F7E3                <1> 	mul	ebx
  3094 00003720 8A15[086E0000]      <1> 	mov 	dl, [minute]
  3095 00003726 01D0                <1> 	add 	eax, edx
  3096                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3097                              <1> 	;mov 	ebx, 60
  3098 00003728 F7E3                <1> 	mul	ebx
  3099 0000372A 8A15[0A6E0000]      <1> 	mov 	dl, [second]
  3100 00003730 01D0                <1> 	add 	eax, edx
  3101                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3102 00003732 C3                  <1> 	retn
  3103                              <1> 
  3104                              <1> get_rtc_time:
  3105                              <1> 	; 15/03/2015
  3106                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3107                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3108                              <1> 	; INT 1Ah
  3109                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3110                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3111                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3112                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3113                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3114                              <1> 	;								
  3115                              <1> RTC_20: 				; GET RTC TIME
  3116 00003733 FA                  <1> 	cli
  3117 00003734 E805D4FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3118 00003739 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3119                              <1> 
  3120 0000373B B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3121 0000373D E8E6D3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3122 00003742 88C6                <1> 	MOV	DH, AL			; SAVE
  3123 00003744 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3124 00003746 E8DDD3FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3125 0000374B 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3126 0000374D 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3127 0000374F B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3128 00003751 E8D2D3FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3129 00003756 88C1                <1> 	MOV	CL, AL			; SAVE
  3130 00003758 B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3131 0000375A E8C9D3FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3132 0000375F 88C5                <1> 	MOV	CH, AL			; SAVE
  3133 00003761 F8                  <1> 	CLC				; SET CY= 0
  3134                              <1> RTC_29:
  3135 00003762 FB                  <1> 	sti
  3136 00003763 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3137                              <1> 
  3138                              <1> get_rtc_date:
  3139                              <1> 	; 15/03/2015
  3140                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3141                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3142                              <1> 	; INT 1Ah
  3143                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3144                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3145                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3146                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3147                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3148                              <1> 	;
  3149                              <1> RTC_40: 				; GET RTC DATE
  3150 00003764 FA                  <1> 	cli
  3151 00003765 E8D4D3FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3152 0000376A 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3153                              <1> 
  3154 0000376C B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3155 0000376E E8B5D3FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3156 00003773 88C2                <1> 	MOV	DL, AL			; SAVE
  3157 00003775 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3158 00003777 E8ACD3FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3159 0000377C 88C6                <1> 	MOV	DH, AL			; SAVE
  3160 0000377E B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3161 00003780 E8A3D3FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3162 00003785 88C1                <1> 	MOV	CL, AL			; SAVE
  3163 00003787 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3164 00003789 E89AD3FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3165 0000378E 88C5                <1> 	MOV	CH, AL			; SAVE
  3166 00003790 F8                  <1> 	CLC				; SET CY=0
  3167                              <1> RTC_49:
  3168 00003791 FB                  <1> 	sti
  3169 00003792 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3170                              <1> 
  3171                              <1> set_date_time:
  3172                              <1> convert_from_epoch:
  3173                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3174                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3175                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3176                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3177                              <1> 	;
  3178                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3179                              <1> 	;
  3180                              <1> 	; Derived from DALLAS Semiconductor
  3181                              <1> 	; Application Note 31 (DS1602/DS1603)
  3182                              <1> 	; 6 May 1998
  3183                              <1> 	;
  3184                              <1> 	; INPUT:
  3185                              <1> 	; EAX = Unix (Epoch) Time
  3186                              <1> 	;
  3187 00003793 31D2                <1> 	xor 	edx, edx
  3188 00003795 B93C000000          <1> 	mov 	ecx, 60
  3189 0000379A F7F1                <1> 	div	ecx
  3190                              <1> 	;mov 	[imin], eax   ; whole minutes
  3191                              <1> 			  ; since 1/1/1970
  3192 0000379C 668915[0A6E0000]    <1> 	mov 	[second], dx  ; leftover seconds
  3193 000037A3 29D2                <1> 	sub 	edx, edx
  3194 000037A5 F7F1                <1> 	div	ecx
  3195                              <1> 	;mov 	[ihrs], eax   ; whole hours
  3196                              <1> 	;		      ; since 1/1/1970
  3197 000037A7 668915[086E0000]    <1> 	mov 	[minute], dx  ; leftover minutes
  3198 000037AE 31D2                <1> 	xor	edx, edx
  3199                              <1> 	;mov 	cx, 24
  3200 000037B0 B118                <1> 	mov 	cl, 24
  3201 000037B2 F7F1                <1> 	div	ecx
  3202                              <1> 	;mov 	[iday], ax   ; whole days
  3203                              <1> 			     ; since 1/1/1970
  3204 000037B4 668915[066E0000]    <1> 	mov 	[hour], dx   ; leftover hours
  3205 000037BB 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3206                              <1> 			     ; 1/1/1968 	
  3207                              <1> 	;mov 	[iday], ax
  3208 000037C0 50                  <1> 	push 	eax
  3209 000037C1 29D2                <1> 	sub	edx, edx
  3210 000037C3 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3211 000037C8 F7F1                <1> 	div	ecx
  3212 000037CA 59                  <1> 	pop 	ecx
  3213                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3214 000037CB 6652                <1> 	push 	dx
  3215                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3216 000037CD 6683FA3C            <1> 	cmp 	dx, 31 + 29  ; if past feb 29 then
  3217 000037D1 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3218 000037D2 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3219                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3220                              <1> 	;mov 	cx, [iday]
  3221 000037D5 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3222 000037D6 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3223 000037D8 B96D010000          <1> 	mov 	ecx, 365
  3224 000037DD 31D2                <1> 	xor	edx, edx
  3225                              <1> 	; EAX = iday-lday, EDX = 0
  3226 000037DF F7F1                <1> 	div	ecx
  3227                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3228                              <1> 	;jday = iday - (iyrs*365) - lday
  3229                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3230                              <1> 	;add	eax, 1968
  3231 000037E1 6605B007            <1> 	add 	ax, 1968     ; compute year
  3232 000037E5 66A3[006E0000]      <1> 	mov 	[year], ax
  3233 000037EB 6689D1              <1> 	mov 	cx, dx
  3234                              <1> 	;mov 	dx, [qday]
  3235 000037EE 665A                <1> 	pop 	dx
  3236 000037F0 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3237 000037F5 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3238 000037F7 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3239 000037FB F5                  <1>         cmc		     ; add a leap day to the # of whole
  3240 000037FC 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3241                              <1> cfe1:			
  3242                              <1> 	;mov 	[jday], cx
  3243 00003800 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3244 00003804 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3245 00003808 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3246                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3247 0000380C 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3248 0000380F 731D                <1> 	jnb 	short cfe3
  3249 00003811 664B                <1> 	dec 	bx           ; month = month - 1
  3250 00003813 66D1E3              <1> 	shl 	bx, 1 
  3251 00003816 668B93[0C6E0000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3252 0000381D 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3253 00003820 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3254 00003824 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3255 00003826 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3256 00003828 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3257 0000382A 6642                <1> 	inc 	dx           ; mday = mday + 1
  3258 0000382C EBDE                <1> 	jmp 	short cfe2
  3259                              <1> cfe3:
  3260 0000382E 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3261 00003830 66891D[026E0000]    <1> 	mov 	[month], bx
  3262 00003837 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3263 0000383A 6641                <1> 	inc 	cx 			  
  3264 0000383C 66890D[046E0000]    <1> 	mov 	[day], cx
  3265                              <1> 	
  3266                              <1> 	; eax, ebx, ecx, edx is changed at return
  3267                              <1> 	; output ->
  3268                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3269                              <1> 	
  3270                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3271                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3272                              <1> set_date:
  3273 00003843 A0[016E0000]        <1>         mov     al, [year+1]
  3274 00003848 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3275 0000384A D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3276                              <1> 			     ; AL = AH * 10h + AL
  3277 0000384C 88C5                <1> 	mov 	ch, al ; century (BCD)
  3278 0000384E A0[006E0000]        <1> 	mov 	al, [year]
  3279 00003853 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3280 00003855 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3281                              <1> 			     ; AL = AH * 10h + AL
  3282 00003857 88C1                <1> 	mov 	cl, al ; year (BCD)
  3283 00003859 A0[026E0000]        <1>         mov 	al, [month]
  3284 0000385E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3285 00003860 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3286                              <1> 			     ; AL = AH * 10h + AL
  3287 00003862 88C6                <1> 	mov 	dh, al ; month (BCD)
  3288 00003864 A0[046E0000]        <1> 	mov 	al, [day]
  3289 00003869 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3290 0000386B D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3291                              <1> 			     ; AL = AH * 10h + AL
  3292 0000386D 88C6                <1> 	mov 	dh, al ; day (BCD)
  3293                              <1> 	; Set real-time clock date
  3294 0000386F E879000000          <1> 	call	set_rtc_date
  3295                              <1> set_time:
  3296                              <1>         ; Read real-time clock time 
  3297                              <1> 	; (get day light saving time bit status)
  3298 00003874 FA                  <1>  	cli
  3299 00003875 E8C4D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3300                              <1> 	; cf = 1 -> al = 0
  3301 0000387A 7207                <1>         jc      short stime1
  3302 0000387C B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3303 0000387E E8A5D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3304                              <1> stime1:
  3305 00003883 FB                  <1> 	sti
  3306 00003884 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3307 00003886 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3308                              <1> 	; DL = 1 or 0 (day light saving time)
  3309                              <1> 	;	
  3310 00003888 A0[066E0000]        <1> 	mov 	al, [hour]
  3311 0000388D D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3312 0000388F D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3313                              <1> 			     ; AL = AH * 10h + AL
  3314 00003891 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3315 00003893 A0[086E0000]        <1>         mov     al, [minute]
  3316 00003898 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3317 0000389A D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3318                              <1> 			     ; AL = AH * 10h + AL
  3319 0000389C 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3320 0000389E A0[0A6E0000]        <1>         mov     al, [second]
  3321 000038A3 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3322 000038A5 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3323                              <1> 			     ; AL = AH * 10h + AL
  3324 000038A7 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3325                              <1> 	; Set real-time clock time
  3326                              <1>  	; call	set_rtc_time
  3327                              <1> set_rtc_time:
  3328                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3329                              <1> 	; 15/03/2015
  3330                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3331                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3332                              <1> 	; INT 1Ah
  3333                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3334                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3335                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3336                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3337                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3338                              <1> 	;								:
  3339                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3340                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3341                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3342                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3343                              <1> 	;
  3344                              <1> RTC_30: 				; SET RTC TIME
  3345 000038A9 FA                  <1> 	cli
  3346 000038AA E88FD2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3347 000038AF 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3348 000038B1 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3349                              <1> RTC_35:
  3350 000038B6 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3351 000038B8 B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3352 000038BA E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3353 000038BF 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3354 000038C1 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3355 000038C3 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3356 000038C8 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3357 000038CA B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3358 000038CC E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3359                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3360 000038D1 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3361 000038D5 E84ED2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3362 000038DA 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3363 000038DC 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3364 000038DE 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3365 000038E1 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3366 000038E3 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3367 000038E5 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3368 000038EA F8                  <1> 	CLC				; SET CY= 0
  3369 000038EB FB                  <1> 	sti
  3370 000038EC C3                  <1> 	RETn				; RETURN WITH CY= 0
  3371                              <1> 
  3372                              <1> set_rtc_date:
  3373                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3374                              <1> 	; 15/03/2015
  3375                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3376                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3377                              <1> 	; INT 1Ah
  3378                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3379                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3380                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3381                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3382                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3383                              <1> 	;
  3384                              <1> RTC_50: 				; SET RTC DATE
  3385 000038ED FA                  <1> 	cli
  3386 000038EE E84BD2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3387 000038F3 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3388 000038F5 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3389                              <1> RTC_55:
  3390 000038FA 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3391 000038FE E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3392 00003903 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3393 00003905 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3394 00003907 E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3395 0000390C 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3396 0000390E B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3397 00003910 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3398 00003915 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3399 00003917 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3400 00003919 E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3401 0000391E 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3402 00003920 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3403 00003922 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3404                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3405 00003927 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3406 0000392B E8F8D1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3407 00003930 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3408 00003932 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3409 00003934 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3410 00003939 F8                  <1> 	CLC				; SET CY= 0
  3411 0000393A FB                  <1> 	sti
  3412 0000393B C3                  <1> 	RETn				; RETURN CY=0
  3413                              <1> 
  3414                              <1> 	; 15/03/2015
  3415                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3416 0000393C B426                <1> 	mov	ah, 26h
  3417 0000393E B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3418 00003940 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3419 00003945 B482                <1> 	mov	ah, 82h
  3420 00003947 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3421 00003949 E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3422 0000394E B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3423 00003950 E8D3D1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3424 00003955 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3425                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3426                              <1> 	;RETn
  3427                              <1> 	; 06/02/2022
  3428 00003957 E9CCD1FFFF          <1> 	jmp	CMOS_READ
  3429                              <1> 
  3430                              <1> 	; 15/03/2015
  3431                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3432                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3433 0000395C 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3434                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3435 0000395D D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3436 0000395F F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3437 00003960 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3438 00003962 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3439 00003963 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3440 00003965 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3441 00003967 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3442 00003969 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3443 0000396B D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3444 0000396D E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3445 0000396F 90                  <1> 	nop			; I/O DELAY
  3446 00003970 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3447                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3448 00003972 9D                  <1> 	popf	
  3449 00003973 C3                  <1> 	RETn
  3450                              <1> 
  3451                              <1> bf_init:
  3452                              <1> 	; 21/03/2022 (Retro UNIX 386 v1.2)
  3453                              <1> 	; 28/11/2021
  3454                              <1> 	; 14/08/2015
  3455                              <1> 	; 02/07/2015
  3456                              <1> 	; 01/07/2015
  3457                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3458                              <1> 	; Buffer (pointer) initialization !
  3459                              <1> 	; 
  3460                              <1> 	; 17/07/2013 - 24/07/2013
  3461                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3462                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3463                              <1> 	;
  3464 00003974 BF[68750000]        <1> 	mov	edi, bufp 
  3465 00003979 B8[988C0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3466 0000397E 29D2                <1> 	sub	edx, edx
  3467 00003980 FECA                <1> 	dec	dl
  3468 00003982 31C9                <1> 	xor	ecx, ecx
  3469 00003984 49                  <1> 	dec	ecx
  3470                              <1> bi0:
  3471 00003985 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3472 0000398A AB                  <1> 	stosd
  3473 0000398B 89C6                <1> 	mov	esi, eax
  3474 0000398D 8916                <1> 	mov	[esi], edx ; 000000FFh
  3475                              <1> 			    ; Not a valid device sign
  3476 0000398F 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3477                              <1> 		      ; Not a valid block number sign 	 	
  3478 00003992 3D[68800000]        <1> 	cmp	eax, buffer
  3479 00003997 77EC                <1> 	ja	short bi0
  3480 00003999 B8[50760000]        <1> 	mov	eax, sb0
  3481 0000399E AB                  <1> 	stosd
  3482 0000399F B8[58780000]        <1> 	mov	eax, sb1
  3483 000039A4 AB                  <1> 	stosd
  3484 000039A5 89C6                <1> 	mov	esi, eax ; offset sb1
  3485 000039A7 8916                <1> 	mov	[esi], edx ; 000000FFh
  3486                              <1> 			   ; Not a valid device sign
  3487 000039A9 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3488                              <1> 		      ; Not a valid block number sign 	 
  3489                              <1> 	; 14/08/2015
  3490                              <1> 	;call 	rdev_init
  3491                              <1> 	;retn
  3492                              <1> 
  3493                              <1> ; ----- Root file system initialization
  3494                              <1> 	
  3495                              <1> 	; 21/03/2022 - Retro UNIX 386 v1.2
  3496                              <1> 	;	(Retro UNIX -runix- v2 file system) 
  3497                              <1> 	; 28/11/2021
  3498                              <1> rdev_init: ; root device, super block buffer initialization
  3499                              <1> 	; 14/08/2015
  3500                              <1> 	; Retro UNIX 386 v1 feature only !
  3501                              <1> 	;
  3502                              <1> 	; NOTE: Disk partitions (file systems), logical
  3503                              <1> 	; drive initialization, partition's start sector etc.
  3504                              <1> 	; will be coded here, later in 'ldrv_init'	
  3505                              <1> 
  3506 000039AC 0FB605[8A6B0000]    <1> 	movzx	eax, byte [boot_drv]
  3507                              <1> rdi_0:
  3508 000039B3 3C80                <1> 	cmp	al, 80h
  3509 000039B5 7202                <1> 	jb	short rdi_1
  3510 000039B7 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3511                              <1> rdi_1:
  3512 000039B9 A2[8E750000]        <1> 	mov	[rdev], al
  3513                              <1> 	; 21/03/2022
  3514                              <1> 	;cmp	al, 2
  3515                              <1> 	;jnb	short rdi_2
  3516 000039BE 08C0                <1> 	or	al, al
  3517 000039C0 7504                <1> 	jnz	short rdi_2 ; hard disk boot
  3518                              <1> 	; floppy disk boot
  3519 000039C2 31D2                <1> 	xor	edx, edx ; device number = 0
  3520                              <1> 			 ; (& fglags = 0)
  3521                              <1> 	; eax = 0 ; boot sector address = 0
  3522                              <1> 	;jmp	short rdi_5
  3523 000039C4 EB22                <1> 	jmp	short rdi_4
  3524                              <1> rdi_2:
  3525                              <1> 	; load masterboot sector
  3526                              <1> 	; to get runix v2 partition's boot sector address
  3527                              <1> 	;	
  3528 000039C6 BB[607A0000]        <1> 	mov	ebx, mbrbuf ; masterboot buffer header addr
  3529                              <1> 	;mov	[ebx], eax
  3530 000039CB 8803                <1> 	mov	[ebx], al
  3531                              <1> 	;sub	al, al
  3532                              <1> 	;; eax = 0
  3533                              <1> 	;mov	[ebx+4], eax ; masterboot sector address
  3534 000039CD E81F2A0000          <1> 	call	diskio
  3535 000039D2 730A                <1> 	jnc	short rdi_3
  3536                              <1> rdi_err:
  3537 000039D4 BE[FB390000]        <1> 	mov	esi, disk_read_err_msg
  3538 000039D9 E9ABF9FFFF          <1> 	jmp	key_to_reboot
  3539                              <1> 
  3540                              <1> rdi_3:
  3541                              <1> 	; [ebx+8] = masterboot buffer (data) address 
  3542                              <1> 	;cmp	word [ebx+8+510], 0AA55h
  3543                              <1> 	;jc	short rdi_err
  3544                              <1> 
  3545 000039DE 8D7308              <1> 	lea	esi, [ebx+8] 
  3546 000039E1 E82D000000          <1> 	call	runix_p_bs    ; return start sector address of
  3547                              <1> 			      ; retro unix v2 partition in esi
  3548                              <1> 	;;jc	short rdi_err ; 'retn'
  3549                              <1> 	;jnc	short rdi_4 ; Runix v2 partition not found !?
  3550                              <1> 			    ; 21/03/2022	
  3551                              <1> 			    ; ((Here, if cf is 1, that means,
  3552                              <1> 			    ; runix v2 partition not found
  3553                              <1> 			    ; in the MBR partition table.
  3554                              <1> 			    ; But, at least, there is a valid
  3555                              <1> 			    ; runix v2 boot sector on the disk
  3556                              <1> 			    ; which started the kernel.
  3557                              <1> 			    ; So, runix v2 boot sector code
  3558                              <1> 			    ; may -must- be on physical sector 0
  3559                              <1> 			    ; and then the superblock may be
  3560                              <1> 			    ; -must be- on physical sector 1.)) 
  3561                              <1> 	;sub	eax, eax
  3562                              <1> 	; eax = 0
  3563                              <1> ;rdi_4:
  3564 000039E6 8B13                <1> 	mov	edx, [ebx] ; restore device number in dl
  3565                              <1> ;rdi_5:
  3566                              <1> rdi_4:
  3567 000039E8 BB[50760000]        <1>         mov	ebx, sb0 ; super block buffer (header)
  3568                              <1> 
  3569 000039ED 40                  <1> 	inc	eax	; default sector address of the sb
  3570                              <1> 			; (boot sector address + 1)
  3571                              <1> 
  3572                              <1> 	;mov 	[ebx], eax
  3573                              <1> 	;mov	al, 1 ; eax = 1
  3574                              <1> 	;mov	[ebx+4], eax ; super block address on disk
  3575                              <1> 	; 21/03/2022
  3576 000039EE 8913                <1> 	mov	[ebx], edx ; device number in DL
  3577                              <1> 			   ; (other bytes -flags- are zero)
  3578 000039F0 894304              <1> 	mov	[ebx+4], eax ; superblock address on disk
  3579                              <1> 
  3580                              <1> 	;call 	diskio
  3581                              <1> 	;retn
  3582                              <1> 	; 28/11/2021
  3583                              <1> 	;jmp	diskio
  3584                              <1> 
  3585                              <1> 	; 21/03/2022
  3586 000039F3 E8F9290000          <1> 	call	diskio
  3587 000039F8 72DA                <1> 	jc	short rdi_err
  3588                              <1> 
  3589                              <1> 	; 21/03/2022
  3590                              <1> 	; Note: If superblock is defective or SB sector
  3591                              <1> 	;	address is wrong, "ERROR: /etc/init !?"
  3592                              <1> 	;	message will appear after here.
  3593                              <1> 	;	..because /etc/init inode will not be found..
  3594                              <1> 	;	So, i am not writing SB validation
  3595                              <1> 	;	(check) code here.
  3596                              <1> 	;
  3597                              <1> 	; ((Also, if we are here, everything should be normal!))
  3598                              <1> 
  3599 000039FA C3                  <1> 	retn
  3600                              <1> 
  3601                              <1> disk_read_err_msg:
  3602                              <1> 	; 21/03/2022 - Retro UNIX 386 v1.2
  3603 000039FB 070D0A              <1> 	db 07h, 0Dh, 0Ah
  3604 000039FE 4469736B2072656164- <1> 	db "Disk read error ! "
  3604 00003A07 206572726F72202120  <1>
  3605 00003A10 0D0A00              <1> 	db 0Dh, 0Ah, 0
  3606                              <1> 
  3607                              <1> 	; 21/03/2022 - Retro UNIX 386 v1.2
  3608                              <1> runix_p_bs:
  3609                              <1> 	; get retro unix v2 partition's boot sector address
  3610                              <1> 	
  3611                              <1> 	; 09/05/2021
  3612                              <1> 	; 19/04/2021 - Retro UNIX 386 v2
  3613                              <1> 	; INPUT:
  3614                              <1> 	;	;;Masterboot buffer at offset mbrbuf
  3615                              <1> 	;	; 21/03/2022
  3616                              <1> 	;	esi = Masterboot buffer (data) address
  3617                              <1> 	; OUTPUT:
  3618                              <1> 	;	;;esi = start sector addr of retro unix v2 fs
  3619                              <1> 	;	; 21/03/2022
  3620                              <1> 	;	eax = start sector address of retro unix v2 fs
  3621                              <1> 	;
  3622                              <1> 	;	cf = 1 -> error, retro unix fs not found
  3623                              <1> 	;		(eax = 0)	
  3624                              <1> 	;
  3625                              <1> 	; Modified registers: esi, eax
  3626                              <1> 
  3627                              <1> 	ptBootable       equ 0
  3628                              <1> 	ptBeginHead      equ 1
  3629                              <1> 	ptBeginSector    equ 2
  3630                              <1> 	ptBeginCylinder  equ 3
  3631                              <1> 	ptFileSystemID   equ 4
  3632                              <1> 	ptEndHead        equ 5
  3633                              <1> 	ptEndSector      equ 6
  3634                              <1> 	ptEndCylinder    equ 7
  3635                              <1> 	ptStartSector    equ 8
  3636                              <1> 	ptSectors        equ 12
  3637                              <1> 
  3638                              <1> 	FS_RETROUNIX	 equ 71h ; runix v2 partition ID
  3639                              <1> 
  3640                              <1> 	;cmp	word [mbrbuf+510], 0AA55h
  3641 00003A13 6681BEFE01000055AA  <1> 	cmp	word [esi+510], 0AA55h
  3642 00003A1C 7515                <1> 	jne	short runix_p_nf
  3643                              <1> 
  3644                              <1> 	; partition table entries are at offset 1BEh
  3645                              <1> 	;mov	esi, mbrbuf+1BEh+ptFileSystemID
  3646 00003A1E 81C6C2010000        <1> 	add	esi, 1BEh+ptFileSystemID
  3647 00003A24 8D4640              <1> 	lea	eax, [esi+(4*16)] 
  3648                              <1> runix_p_bs_0:
  3649 00003A27 803E71              <1> 	cmp	byte [esi], FS_RETROUNIX ; 71h
  3650 00003A2A 740B                <1> 	je	short runix_p_f ; it is retro unix partition
  3651 00003A2C 83C610              <1> 	add	esi, 16
  3652                              <1> 	;cmp	esi, mbrbuf+1BEh+ptFileSystemID+(4*16) 
  3653 00003A2F 39C6                <1> 	cmp	esi, eax
  3654 00003A31 72F4                <1> 	jb	short runix_p_bs_0 	  
  3655                              <1> runix_p_nf:
  3656 00003A33 29C0                <1> 	sub	eax, eax
  3657                              <1> 	; eax = 0
  3658 00003A35 F9                  <1> 	stc
  3659 00003A36 C3                  <1> 	retn
  3660                              <1> runix_p_f:
  3661                              <1> 	;mov	esi, [esi+ptStartSector-ptFileSystemID]
  3662 00003A37 8B4604              <1> 	mov	eax, [esi+ptStartSector-ptFileSystemID]
  3663 00003A3A C3                  <1> 	retn
  3664                              <1> 
  3665                              <1> ; 23/10/2015
  3666                              <1> com1_irq4:
  3667 00003A3B [433A0000]          <1> 	dd dummy_retn
  3668                              <1> com2_irq3:
  3669 00003A3F [433A0000]          <1> 	dd dummy_retn
  3670                              <1> 
  3671                              <1> dummy_retn:
  3672 00003A43 C3                  <1> 	retn
  2087                                  %include 'u1.s'      ; 10/05/2015
  2088                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2089                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2090                              <1> ; ****************************************************************************
  2091                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2092                              <1> ; Last Modification: 13/03/2022 (Retro UNIX 386 v1.2)
  2093                              <1> ; ----------------------------------------------------------------------------
  2094                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2095                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2096                              <1> ;
  2097                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2098                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2099                              <1> ; <Bell Laboratories (17/3/1972)>
  2100                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2101                              <1> ;
  2102                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2103                              <1> ;
  2104                              <1> ; ****************************************************************************
  2105                              <1> 
  2106                              <1> unkni: ; / used for all system calls
  2107                              <1> sysent: ; < enter to system call >
  2108                              <1> 	; 25/12/2021 (Retro UNIX 386 v1.2)
  2109                              <1> 	; 19/10/2015
  2110                              <1> 	; 21/09/2015
  2111                              <1> 	; 01/07/2015
  2112                              <1> 	; 19/05/2015
  2113                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2114                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2115                              <1> 	;
  2116                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2117                              <1> 	; The trap type is determined and an indirect jump is made to 
  2118                              <1> 	; the appropriate system call handler. If there is a trap inside
  2119                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2120                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2121                              <1> 	; instructor is decoded to get the the system code part (see
  2122                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2123                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2124                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2125                              <1> 	; is called. If the call is legitimate control passes to the
  2126                              <1> 	; appropriate system routine.
  2127                              <1> 	;
  2128                              <1> 	; Calling sequence:
  2129                              <1> 	;	Through a trap caused by any sys call outside the system.
  2130                              <1> 	; Arguments:
  2131                              <1> 	;	Arguments of particular system call.	
  2132                              <1> 	; ...............................................................
  2133                              <1> 	;	
  2134                              <1> 	; Retro UNIX 8086 v1 modification: 
  2135                              <1> 	;       System call number is in EAX register.
  2136                              <1> 	;
  2137                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2138                              <1> 	;	registers depending of function details.
  2139                              <1>   	;
  2140                              <1> 	; 16/04/2015
  2141 00003A44 368925[A4750000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2142                              <1> 	; save user registers
  2143 00003A4B 1E                  <1> 	push	ds
  2144 00003A4C 06                  <1> 	push	es
  2145 00003A4D 0FA0                <1> 	push	fs
  2146 00003A4F 0FA8                <1> 	push	gs
  2147 00003A51 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2148                              <1> 	;
  2149                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2150                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2151                              <1> 	;	for saving/restoring user registers.)
  2152                              <1> 	;
  2153 00003A52 50                  <1> 	push	eax ; 01/07/2015
  2154 00003A53 66B81000            <1> 	mov     ax, KDATA
  2155 00003A57 8ED8                <1>         mov     ds, ax
  2156 00003A59 8EC0                <1>         mov     es, ax
  2157 00003A5B 8EE0                <1>         mov     fs, ax
  2158 00003A5D 8EE8                <1>         mov     gs, ax
  2159 00003A5F A1[98700000]        <1> 	mov	eax, [k_page_dir]
  2160 00003A64 0F22D8              <1> 	mov	cr3, eax
  2161 00003A67 58                  <1> 	pop	eax ; 01/07/2015
  2162                              <1> 	; 19/10/2015
  2163 00003A68 FC                  <1> 	cld
  2164                              <1> 	;
  2165 00003A69 FE05[A2750000]      <1> 	inc	byte [sysflg]
  2166                              <1> 		; incb sysflg / indicate a system routine is in progress
  2167 00003A6F FB                  <1>         sti 	; 18/01/2014
  2168                              <1> 	;jnz	panic ; 24/05/2013
  2169                              <1> 	; 04/12/2021
  2170 00003A70 7405                <1> 	jz	short _1
  2171 00003A72 E90DF9FFFF          <1> 	jmp	panic
  2172                              <1> 		; beq 1f
  2173                              <1> 		; jmp panic ; / called if trap inside system
  2174                              <1> ;1:
  2175                              <1> _1:	; 04/12/2021
  2176                              <1> 	; 16/04/2015
  2177 00003A77 A3[AC750000]        <1> 	mov	[u.r0], eax
  2178 00003A7C 8925[A8750000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2179                              <1> 	;
  2180                              <1> 		; mov $s.syst+2,clockp
  2181                              <1> 		; mov r0,-(sp) / save user registers 
  2182                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2183                              <1> 			   ; / in u.r0
  2184                              <1> 		; mov r1,-(sp)
  2185                              <1> 		; mov r2,-(sp)
  2186                              <1> 		; mov r3,-(sp)
  2187                              <1> 		; mov r4,-(sp)
  2188                              <1> 		; mov r5,-(sp)
  2189                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2190                              <1> 		             ; / arithmetic unit
  2191                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2192                              <1> 		             ; / extended arithmetic unit
  2193                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2194                              <1> 		             ; / arithmetic unit
  2195                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2196                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2197                              <1> 		; mov -(r0),r0 / sys inst in r0 10400xxx
  2198                              <1> 		; sub $sys,r0 / get xxx code
  2199 00003A82 C1E002              <1> 	shl	eax, 2
  2200                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2201 00003A85 3DA0000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2202                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2203                              <1> 	;jnb	short badsys
  2204                              <1> 		; bhis badsys / yes, bad system call
  2205                              <1> 	; 25/12/2021
  2206 00003A8A 7205                <1> 	jb	short _2
  2207 00003A8C E969010000          <1> 	jmp	badsys
  2208                              <1> _2:
  2209                              <1> 	; 25/12/2021
  2210                              <1> 	;cmc
  2211                              <1> 	;pushf	
  2212                              <1> 	;push	eax
  2213 00003A91 8B2D[A4750000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2214                              <1> 	;mov	al, 0FEh ; 11111110b
  2215                              <1> 	;;adc	al, 0 ; al = al + cf
  2216                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2217 00003A97 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2218                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2219                              <1> 				 ; / and clear carry bit
  2220                              <1> 	;pop	ebp ; eax
  2221 00003A9B 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2222                              <1> 	;popf
  2223                              <1>         ;;jc	badsys
  2224                              <1> 	;; 04/12/2021
  2225                              <1> 	;jnc	short _3
  2226                              <1> 	;jmp	badsys
  2227                              <1> ;_3:
  2228 00003A9D A1[AC750000]        <1> 	mov	eax, [u.r0]
  2229                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2230 00003AA2 FFA5[A83A0000]      <1> 	jmp	dword [ebp+syscalls]
  2231                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2232                              <1> 		            ; / to proper system routine.
  2233                              <1> 
  2234                              <1> 	; 09/01/2022
  2235                              <1> 	; 01/01/2022 (/etc/init error, BugFix efforts, test)
  2236                              <1> syscalls: ; 1:
  2237                              <1> 	; 21/09/2015
  2238                              <1> 	; 01/07/2015
  2239                              <1> 	; 16/04/2015 (32 bit address modification) 
  2240 00003AA8 [C43B0000]          <1> 	dd sysrele	; / 0
  2241 00003AAC [6C3C0000]          <1> 	dd sysexit 	; / 1
  2242 00003AB0 [973D0000]          <1> 	dd sysfork 	; / 2
  2243 00003AB4 [9C3E0000]          <1> 	dd sysread 	; / 3
  2244 00003AB8 [B13E0000]          <1> 	dd syswrite 	; / 4
  2245 00003ABC [143F0000]          <1> 	dd sysopen 	; / 5
  2246 00003AC0 [44400000]          <1> 	dd sysclose 	; / 6
  2247 00003AC4 [123D0000]          <1> 	dd syswait 	; / 7
  2248 00003AC8 [AC3F0000]          <1> 	dd syscreat 	; / 8
  2249 00003ACC [FA430000]          <1> 	dd syslink 	; / 9
  2250 00003AD0 [88440000]          <1> 	dd sysunlink 	; / 10
  2251 00003AD4 [A8450000]          <1> 	dd sysexec 	; / 11
  2252 00003AD8 [C54B0000]          <1> 	dd syschdir 	; / 12
  2253 00003ADC [C74C0000]          <1> 	dd systime 	; / 13
  2254 00003AE0 [F33F0000]          <1> 	dd sysmkdir 	; / 14
  2255 00003AE4 [044C0000]          <1> 	dd syschmod 	; / 15
  2256 00003AE8 [334C0000]          <1> 	dd syschown 	; / 16
  2257 00003AEC [FB4C0000]          <1> 	dd sysbreak 	; / 17
  2258 00003AF0 [48490000]          <1> 	dd sysstat 	; / 18
  2259 00003AF4 [0B4E0000]          <1> 	dd sysseek 	; / 19
  2260 00003AF8 [1D4E0000]          <1> 	dd systell 	; / 20
  2261 00003AFC [4F5D0000]          <1> 	dd sysmount 	; / 21
  2262 00003B00 [295E0000]          <1> 	dd sysumount 	; / 22
  2263 00003B04 [8E4E0000]          <1> 	dd syssetuid 	; / 23
  2264 00003B08 [C34E0000]          <1> 	dd sysgetuid 	; / 24
  2265 00003B0C [D64C0000]          <1> 	dd sysstime 	; / 25
  2266 00003B10 [824E0000]          <1> 	dd sysquit 	; / 26
  2267 00003B14 [764E0000]          <1> 	dd sysintr 	; / 27
  2268 00003B18 [2F490000]          <1> 	dd sysfstat 	; / 28
  2269 00003B1C [5F400000]          <1> 	dd sysemt 	; / 29
  2270 00003B20 [AD400000]          <1> 	dd sysmdate 	; / 30
  2271 00003B24 [0A410000]          <1> 	dd sysstty 	; / 31
  2272 00003B28 [F4420000]          <1> 	dd sysgtty 	; / 32
  2273 00003B2C [A8400000]          <1> 	dd sysilgins 	; / 33
  2274 00003B30 [A9660000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2275                              <1> 			     ; 11/06/2014
  2276 00003B34 [D6660000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2277                              <1> 			     ; 01/07/2015
  2278 00003B38 [AE670000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2279                              <1> 			     ; 21/09/2015 - get last error number
  2280                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  2281                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  2282 00003B3C [DC4E0000]          <1> 	dd syssetgid	; 37
  2283 00003B40 [FF4E0000]          <1> 	dd sysgetgid	; 38
  2284                              <1> 	; 18/06/2021 - Retro UNIX 386 v2 (ref: TRDOS 386 v2)
  2285 00003B44 [144F0000]          <1> 	dd sysver	; 39 ; (get) Retro Unix 386 version
  2286                              <1> 
  2287                              <1> end_of_syscalls:
  2288                              <1> 
  2289                              <1> error:
  2290                              <1> 	; 11/12/2021 (Retro UNIX 386 v1.2)
  2291                              <1> 	; 17/09/2015
  2292                              <1> 	; 03/09/2015
  2293                              <1> 	; 01/09/2015
  2294                              <1> 	; 09/06/2015
  2295                              <1> 	; 13/05/2015
  2296                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2297                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2298                              <1> 	;
  2299                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2300                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2301                              <1> 	;
  2302                              <1> 	; INPUTS -> none
  2303                              <1> 	; OUTPUTS ->
  2304                              <1> 	;	processor status - carry (c) bit is set (means error)
  2305                              <1> 	;
  2306                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2307                              <1> 	; 	      Because, jumps to error procedure
  2308                              <1> 	;	      disrupts push-pop nesting balance)
  2309                              <1> 	;
  2310 00003B48 8B2D[A4750000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2311 00003B4E 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2312                              <1> 				 ; (system call will return with cf = 1)
  2313                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2314                              <1> 		               ; / users stack
  2315                              <1> 	; 17/09/2015
  2316 00003B52 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2317                              <1> 				 ; for saving/restoring user registers	
  2318                              <1> 	;cmp	ebp, [u.usp]
  2319                              <1> 	;je	short err0	
  2320 00003B55 892D[A8750000]      <1> 	mov	[u.usp], ebp
  2321                              <1> ;err0:
  2322                              <1> 	; 01/09/2015
  2323 00003B5B 8B25[A8750000]      <1> 	mov	esp, [u.usp]	; Retro Unix 8086 v1 modification!
  2324                              <1> 				; 10/04/2013
  2325                              <1> 				; (If an I/O error occurs during disk I/O,
  2326                              <1> 				; related procedures will jump to 'error'
  2327                              <1> 				; procedure directly without returning to 
  2328                              <1> 				; the caller procedure. So, stack pointer
  2329                              <1> 				; must be restored here.)
  2330                              <1> 	; 13/05/2015
  2331                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2332                              <1> 	;	'get last error' system call later. 	
  2333                              <1> 
  2334                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2335 00003B61 C605[1E760000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2336                              <1> 
  2337                              <1> sysret: ; < return from system call>
  2338                              <1> 	; 11/12/2021
  2339                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2340                              <1> 	; 30/11/2021
  2341                              <1> 	; 10/09/2015
  2342                              <1> 	; 29/07/2015
  2343                              <1> 	; 25/06/2015
  2344                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2345                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2346                              <1> 	;
  2347                              <1> 	; 'sysret' first checks to see if process is about to be 
  2348                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2349                              <1> 	; If not, following happens:	 
  2350                              <1> 	; 	1) The user's stack pointer is restored.
  2351                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2352                              <1> 	;	   i-node has been modified. If it has, it is written out
  2353                              <1> 	;	   via 'ppoke'.
  2354                              <1> 	;	3) If the super block has been modified, it is written out
  2355                              <1> 	;	   via 'ppoke'.				
  2356                              <1> 	;	4) If the dismountable file system's super block has been
  2357                              <1> 	;	   modified, it is written out to the specified device
  2358                              <1> 	;	   via 'ppoke'.
  2359                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2360                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2361                              <1> 	;	   another user a chance to run.
  2362                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2363                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2364                              <1> 	;
  2365                              <1> 	; Calling sequence:
  2366                              <1> 	;	jump table or 'br sysret'
  2367                              <1> 	; Arguments: 
  2368                              <1> 	;	-	
  2369                              <1> 	; ...............................................................
  2370                              <1> 	;	
  2371                              <1> 	; ((AX=r1 for 'iget' input))
  2372                              <1> 	;	
  2373                              <1> 	;xor	ax, ax ; 04/05/2013
  2374                              <1> 	; 30/11/2021
  2375 00003B68 31C0                <1> 	xor	eax, eax
  2376                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2377 00003B6A FEC0                <1> 	inc	al ; 04/05/2013
  2378 00003B6C 3805[FC750000]      <1> 	cmp	[u.bsys], al ; 1
  2379                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2380                              <1> 	;jnb	sysexit ; 04/05/2013
  2381                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2382                              <1> 	; 04/12/2021
  2383 00003B72 720F                <1> 	jb	short _3
  2384                              <1> 	; 11/12/2021
  2385 00003B74 C705[20760000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2385 00003B7C 0000                <1>
  2386 00003B7E E9E9000000          <1> 	jmp	sysexit
  2387                              <1> _3:
  2388                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2389                              <1> 		; mov u.sp,sp / no point stack to users stack
  2390 00003B83 FEC8                <1> 	dec 	al ; mov ax, 0
  2391                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2392 00003B85 E88B190000          <1> 	call	iget
  2393                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2394                              <1> 		            ; / it is written out
  2395                              <1> 	;xor 	ax, ax ; 0
  2396                              <1> 	; 30/11/2021
  2397 00003B8A 31C0                <1> 	xor	eax, eax
  2398 00003B8C 3805[A0750000]      <1> 	cmp	[smod], al ; 0
  2399                              <1> 		; tstb	smod / has the super block been modified
  2400 00003B92 7614                <1> 	jna	short sysret1
  2401                              <1> 		; beq	1f / no, 1f
  2402 00003B94 A2[A0750000]        <1> 	mov	[smod], al ; 0
  2403                              <1> 		; clrb smod / yes, clear smod
  2404 00003B99 BB[50760000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2405 00003B9E 66810B0002          <1>    	or	word [ebx], 200h ;;
  2406                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2407                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2408                              <1> 		      	      ; / output
  2409                              <1> 	; AX = 0
  2410 00003BA3 E829270000          <1> 	call 	poke ; 07/08/2013
  2411                              <1> 	;call	ppoke
  2412                              <1> 	; AX = 0
  2413                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2414                              <1> sysret1: ;1:
  2415 00003BA8 3805[A1750000]      <1> 	cmp	[mmod], al ; 0
  2416                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2417                              <1> 		           ; / system
  2418 00003BAE 7614                <1> 	jna	short sysrel0
  2419                              <1> 		; beq 1f / been modified?  no, 1f
  2420 00003BB0 A2[A1750000]        <1> 	mov	[mmod], al ; 0	
  2421                              <1> 		; clrb	mmod / yes, clear mmod
  2422                              <1>         ;mov    ax, [mntd]
  2423                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2424 00003BB5 BB[58780000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2425                              <1>         ;;mov	[ebx], al
  2426                              <1> 	;mov    [sb1], al
  2427                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2428 00003BBA 66810B0002          <1> 	or	word [ebx], 200h
  2429                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2430                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2431 00003BBF E80D270000          <1> 	call	poke ; 07/08/2013
  2432                              <1> 	;call	ppoke 
  2433                              <1> 		; jsr r0,ppoke / write it out to its device
  2434                              <1>         ;xor    al, al ; 26/04/2013       
  2435                              <1> ;1:
  2436                              <1> 		; tstb uquant / is the time quantum 0?
  2437                              <1> 		; bne 1f / no, don't swap it out
  2438                              <1> 
  2439                              <1> sysrele: ; < release >
  2440                              <1> 	; 14/10/2015
  2441                              <1> 	; 01/09/2015
  2442                              <1> 	; 24/07/2015
  2443                              <1> 	; 14/05/2015
  2444                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2445                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2446                              <1> 	;
  2447                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2448                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2449                              <1> 	; turns off the system flag. It then checked to see if there is
  2450                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2451                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2452                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2453                              <1> 	; the user, a rti is made.
  2454                              <1> 	;
  2455                              <1> 	; Calling sequence:
  2456                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2457                              <1> 	; Arguments:
  2458                              <1> 	;	-	
  2459                              <1> 	; ...............................................................
  2460                              <1> 	;	
  2461                              <1> 	; 23/02/2014 (swapret)
  2462                              <1> 	; 22/09/2013
  2463                              <1> sysrel0: ;1:
  2464 00003BC4 803D[F4750000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2465                              <1> 		; tstb uquant / is the time quantum 0?
  2466 00003BCB 7705                <1>         ja      short swapret
  2467                              <1> 		; bne 1f / no, don't swap it out
  2468                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2469 00003BCD E8C4130000          <1> 	call	tswap
  2470                              <1> 		; jsr r0,tswap / yes, swap it out
  2471                              <1> ;
  2472                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2473                              <1> swapret: ;1:
  2474                              <1> 	; 10/09/2015
  2475                              <1> 	; 01/09/2015
  2476                              <1> 	; 14/05/2015
  2477                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2478                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2479                              <1> 	; cli
  2480                              <1> 	; 24/07/2015
  2481                              <1> 	;
  2482                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2483                              <1> 	;; mov	esp, [u.usp]
  2484                              <1> 
  2485                              <1> 	; 22/09/2013
  2486 00003BD2 E896150000          <1> 	call	isintr
  2487                              <1> 	; 20/10/2013
  2488 00003BD7 7405                <1> 	jz	short sysrel1
  2489 00003BD9 E877000000          <1> 	call	intract
  2490                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2491                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2492                              <1> 		               ; / action
  2493                              <1> sysrel1:
  2494 00003BDE FA                  <1> 	cli ; 14/10/2015
  2495 00003BDF FE0D[A2750000]      <1> 	dec	byte [sysflg]
  2496                              <1> 		; decb sysflg / turn system flag off
  2497 00003BE5 A1[0C760000]        <1> 	mov     eax, [u.pgdir]
  2498 00003BEA 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2499                              <1> 			  ; (others are different than kernel page tables) 
  2500                              <1> 	; 10/09/2015
  2501 00003BED 61                  <1> 	popad ; edi, esi, ebp, temp (increment esp by 4), ebx, edx, ecx, eax
  2502                              <1> 		; mov (sp)+,sc / restore user registers
  2503                              <1> 		; mov (sp)+,mq
  2504                              <1> 		; mov (sp)+,ac
  2505                              <1> 		; mov (sp)+,r5
  2506                              <1> 		; mov (sp)+,r4
  2507                              <1> 		; mov (sp)+,r3
  2508                              <1> 		; mov (sp)+,r2
  2509                              <1> 	;
  2510 00003BEE A1[AC750000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2511 00003BF3 0FA9                <1> 	pop	gs
  2512 00003BF5 0FA1                <1> 	pop	fs
  2513 00003BF7 07                  <1> 	pop	es
  2514 00003BF8 1F                  <1> 	pop	ds
  2515 00003BF9 CF                  <1> 	iretd	
  2516                              <1> 		; rti / no, return from interrupt
  2517                              <1> 
  2518                              <1> badsys:
  2519                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2520                              <1> 	; (Major Modification: 'core' dumping procedure in
  2521                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2522                              <1> 	;	has been changed to print 'Invalid System Call !'
  2523                              <1> 	;	message on the user's console tty.)
  2524                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2525                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2526                              <1> 	; (EAX = Function number)  
  2527                              <1> 	;
  2528 00003BFA FE05[FC750000]      <1> 	inc	byte [u.bsys]
  2529                              <1> 	;
  2530 00003C00 8B1D[A4750000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2531 00003C06 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2532 00003C08 E8E9DAFFFF          <1> 	call	dwordtohex
  2533 00003C0D 8915[F46D0000]      <1> 	mov	[bsys_msg_eip], edx
  2534 00003C13 A3[F86D0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2535 00003C18 A1[AC750000]        <1> 	mov	eax, [u.r0]
  2536 00003C1D E8D4DAFFFF          <1> 	call	dwordtohex
  2537 00003C22 8915[E46D0000]      <1> 	mov	[bsys_msg_eax], edx
  2538 00003C28 A3[E86D0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2539                              <1> 	; 11/12/2021
  2540                              <1> 	;xor	eax, eax
  2541                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2542                              <1> 	;mov	ebx, [u.fofp]
  2543                              <1> 	;mov	[ebx], eax
  2544                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2545                              <1> 	;inc	eax
  2546                              <1> 	; 11/12/2021 - Retro UNIX 386 v2 fs compatibility 
  2547                              <1> 	; (Retro UNIX 386 v1.2)
  2548                              <1> 	;mov	al, 8 ; /dev/tty inode number (runix v2 fs)
  2549                              <1> 	;; eax = 8 ; inode number of console tty (for user)	
  2550                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2551                              <1> 		; writei
  2552                              <1> 		; INPUTS ->
  2553                              <1> 		;    r1 - inode number
  2554                              <1> 		;    u.count - byte count to be written
  2555                              <1> 		;    u.base - points to user buffer
  2556                              <1> 		;    u.fofp - points to word with current file offset
  2557                              <1> 		; OUTPUTS ->
  2558                              <1> 		;    u.count - cleared
  2559                              <1> 		;    u.nread - accumulates total bytes passed back	
  2560                              <1> 		;
  2561                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2562                              <1> 	;call	writei
  2563                              <1> 	;;mov	eax, 1
  2564                              <1> 	;jmp	sysexit
  2565                              <1> 
  2566                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2567 00003C2D BE[C56D0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2568 00003C32 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2569 00003C39 8A83[D7710000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2570 00003C3F C605[C7700000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2571 00003C46 A2[E1750000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2572 00003C4B E8432B0000          <1> 	call	print_cmsg
  2573                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2574 00003C50 E9F3FEFFFF          <1> 	jmp	error
  2575                              <1> 
  2576                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2577                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2578                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2579                              <1> 		; br 1f / error
  2580                              <1> 		; neg r1 / negate the i-number to open the core image file
  2581                              <1> 		       ; / for writing
  2582                              <1> 		; jsr r0,iopen / open the core image file
  2583                              <1> 		; jsr r0,itrunc / free all associated blocks
  2584                              <1> 		; br 2f
  2585                              <1> ;1:
  2586                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2587                              <1> 		; jsr r0,maknod / make an i-node
  2588                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2589                              <1> ;2:
  2590                              <1> 		; mov $core,u.base / move address core to u.base
  2591                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2592                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2593                              <1> 		; clr u.off / clear user offset
  2594                              <1> 		; jsr r0,writei / write out the core image to the user
  2595                              <1> 		; mov $user,u.base / pt. u.base to user
  2596                              <1> 		; mov $64.,u.count / u.count = 64
  2597                              <1> 		; jsr r0,writei / write out all the user parameters
  2598                              <1> 		; neg r1 / make i-number positive
  2599                              <1> 		; jsr r0,iclose / close the core image file
  2600                              <1> 		; br sysexit /
  2601                              <1> ;3:
  2602                              <1> 		; <core\0\0>
  2603                              <1> 
  2604                              <1> intract: ; / interrupt action
  2605                              <1> 	; 14/10/2015
  2606                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2607                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2608                              <1> 	;
  2609                              <1> 	; Retro UNIX 8086 v1 modification !
  2610                              <1> 	; (Process/task switching and quit routine by using
  2611                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2612                              <1> 	;
  2613                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2614                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2615                              <1> 	;		'intract' will jump to 'sysexit'.
  2616                              <1> 	;	    Intract will return to the caller 
  2617                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2618                              <1> 	; 14/10/2015
  2619 00003C55 FB                  <1> 	sti
  2620                              <1> 	; 07/12/2013	
  2621 00003C56 66FF05[FA750000]    <1> 	inc 	word [u.quit]
  2622 00003C5D 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2623 00003C5F 66FF0D[FA750000]    <1> 	dec	word [u.quit]
  2624                              <1> 	; 16/04/2015
  2625 00003C66 C3                  <1> 	retn
  2626                              <1> intrct0:	
  2627 00003C67 58                  <1> 	pop	eax ; call intract -> retn
  2628                              <1> 	;
  2629 00003C68 31C0                <1> 	xor 	eax, eax
  2630 00003C6A FEC0                <1> 	inc	al  ; mov ax, 1
  2631                              <1> ;;;
  2632                              <1> 	; UNIX v1 original 'intract' routine... 
  2633                              <1> 	; / interrupt action
  2634                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2635                              <1> 		; bne 1f / no, 1f
  2636                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2637                              <1> 	; 1: / now in user area
  2638                              <1> 		; mov r1,-(sp) / save r1
  2639                              <1> 		; mov u.ttyp,r1 
  2640                              <1> 			; / pointer to tty buffer in control-to r1
  2641                              <1> 		; cmpb 6(r1),$177
  2642                              <1> 			; / is the interrupt char equal to "del"
  2643                              <1> 		; beq 1f / yes, 1f
  2644                              <1> 		; clrb 6(r1) 
  2645                              <1> 		        ; / no, clear the byte 
  2646                              <1> 			; / (must be a quit character)
  2647                              <1> 		; mov (sp)+,r1 / restore r1
  2648                              <1> 		; clr u.quit / clear quit flag
  2649                              <1> 		; bis $20,2(sp) 
  2650                              <1> 		    	; / set trace for quit (sets t bit of 
  2651                              <1> 			; / ps-trace trap)
  2652                              <1> 		; rti   ;  / return from interrupt
  2653                              <1> 	; 1: / interrupt char = del
  2654                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2655                              <1> 			   ; / in the buffer
  2656                              <1> 		; mov (sp)+,r1 / restore r1
  2657                              <1> 		; cmp u.intr,$core / should control be 
  2658                              <1> 				; / transferred to loc core?
  2659                              <1> 		; blo 1f
  2660                              <1> 		; jmp *u.intr / user to do rti yes, 
  2661                              <1> 				; / transfer to loc core
  2662                              <1> 	; 1:
  2663                              <1> 		; sys 1 / exit
  2664                              <1> 
  2665                              <1> sysexit: ; <terminate process>
  2666                              <1> 	; 30/11/2021 - etro UNIX 386 v1.2
  2667                              <1> 	; 01/09/2015
  2668                              <1> 	; 31/08/2015
  2669                              <1> 	; 14/05/2015
  2670                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2671                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2672                              <1> 	;
  2673                              <1> 	; 'sysexit' terminates a process. First each file that
  2674                              <1> 	; the process has opened is closed by 'flose'. The process
  2675                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2676                              <1> 	; searched to find children of the dying process. If any of
  2677                              <1> 	; children are zombies (died by not waited for), they are
  2678                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2679                              <1> 	; dying process's parent. When the parent is found, it is
  2680                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2681                              <1> 	; one of these, the dying process just dies. If it is waiting
  2682                              <1> 	; for a child process to die, it notified that it doesn't 
  2683                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2684                              <1> 	; (waiting to active). It is awakened and put on runq by
  2685                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2686                              <1> 	; it will never be run again but stays around until a 'wait'
  2687                              <1> 	; is completed by it's parent process. If the parent is not
  2688                              <1> 	; found, process just dies. This means 'swap' is called with
  2689                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2690                              <1> 	; to write out the process and 'rswap' reads the new process
  2691                              <1> 	; over the one that dies..i.e., the dying process is 
  2692                              <1> 	; overwritten and destroyed.	
  2693                              <1>  	;
  2694                              <1> 	; Calling sequence:
  2695                              <1> 	;	sysexit or conditional branch.
  2696                              <1> 	; Arguments:
  2697                              <1> 	;	-	
  2698                              <1> 	; ...............................................................
  2699                              <1> 	;	
  2700                              <1> 	; Retro UNIX 8086 v1 modification: 
  2701                              <1> 	;       System call number (=1) is in EAX register.
  2702                              <1> 	;
  2703                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2704                              <1> 	;       registers depending of function details.
  2705                              <1> 	;
  2706                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2707                              <1> 	;
  2708                              <1> ; / terminate process
  2709                              <1> 	; AX = 1
  2710                              <1> 	;dec 	ax ; 0
  2711                              <1> 	; 30/11/2021
  2712 00003C6C 48                  <1> 	dec	eax ; 0
  2713 00003C6D 66A3[F8750000]      <1> 	mov	[u.intr], ax ; 0
  2714                              <1> 		; clr u.intr / clear interrupt control word
  2715                              <1> 		; clr r1 / clear r1
  2716                              <1> 	; AX = 0
  2717                              <1> sysexit_1: ; 1:
  2718                              <1> 	; AX = File descriptor
  2719                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2720                              <1> 		; / Search the whole list
  2721 00003C73 E8620D0000          <1> 	call	fclose
  2722                              <1> 		; jsr r0,fclose / close all files the process opened
  2723                              <1> 	;; ignore error return
  2724                              <1> 		; br .+2 / ignore error return
  2725                              <1> 	;inc	ax
  2726 00003C78 FEC0                <1> 	inc	al
  2727                              <1> 		; inc r1 / increment file descriptor
  2728                              <1> 	;cmp	ax, 10
  2729 00003C7A 3C0A                <1> 	cmp	al, 10
  2730                              <1> 		; cmp r1,$10. / end of u.fp list?
  2731 00003C7C 72F5                <1> 	jb	short sysexit_1
  2732                              <1> 		; blt 1b / no, go back
  2733 00003C7E 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2734                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2735 00003C85 88A3[F7710000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2736                              <1> 		; clrb p.stat-1(r1) / free the process
  2737                              <1> 	;shl	bx, 1
  2738 00003C8B D0E3                <1> 	shl	bl, 1
  2739                              <1> 		; asl r1 / use r1 for index into the below tables
  2740 00003C8D 668B8B[96710000]    <1> 	mov	cx, [ebx+p.pid-2]
  2741                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2742 00003C94 668B93[B6710000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2743                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2744                              <1> 	; xor 	bx, bx ; 0
  2745 00003C9B 30DB                <1> 	xor	bl, bl ; 0
  2746                              <1> 		; clr r2
  2747 00003C9D 31F6                <1> 	xor	esi, esi ; 0
  2748                              <1> 		; clr r5 / initialize reg
  2749                              <1> sysexit_2: ; 1:
  2750                              <1> 	        ; / find children of this dying process, 
  2751                              <1> 		; / if they are zombies, free them
  2752                              <1> 	;add	bx, 2
  2753 00003C9F 80C302              <1> 	add	bl, 2
  2754                              <1> 		; add $2,r2 / search parent process table 
  2755                              <1> 		          ; / for dying process's name
  2756 00003CA2 66398B[B6710000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2757                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2758 00003CA9 7513                <1> 	jne	short sysexit_4
  2759                              <1> 		; bne 3f / no
  2760                              <1> 	;shr	bx, 1
  2761 00003CAB D0EB                <1> 	shr	bl, 1
  2762                              <1> 		; asr r2 / yes, it is a parent
  2763 00003CAD 80BB[F7710000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2764                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2765                              <1> 				     ; / dying process a zombie
  2766 00003CB4 7506                <1> 	jne	short sysexit_3 
  2767                              <1> 		; bne 2f / no
  2768 00003CB6 88A3[F7710000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2769                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2770                              <1> sysexit_3: ; 2:
  2771                              <1> 	;shr	bx, 1
  2772 00003CBC D0E3                <1> 	shl	bl, 1
  2773                              <1> 		; asl r2
  2774                              <1> sysexit_4: ; 3:
  2775                              <1> 		; / search the process name table 
  2776                              <1> 		; / for the dying process's parent
  2777 00003CBE 663993[96710000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2778                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2779 00003CC5 7502                <1> 	jne	short sysexit_5
  2780                              <1> 		; bne 3f / no
  2781 00003CC7 89DE                <1> 	mov	esi, ebx
  2782                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2783                              <1> 		          ; / process # x2) in r5
  2784                              <1> sysexit_5: ; 3:
  2785                              <1> 	;cmp	bx, nproc + nproc
  2786 00003CC9 80FB20              <1> 	cmp	bl, nproc + nproc
  2787                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2788 00003CCC 72D1                <1> 	jb	short sysexit_2
  2789                              <1> 		; blt 1b / no, go back
  2790                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2791 00003CCE 21F6                <1> 	and	esi, esi ; r5=r1
  2792 00003CD0 7431                <1> 	jz	short sysexit_6
  2793                              <1> 		; beq 2f / no parent has been found. 
  2794                              <1> 		       ; / The process just dies
  2795 00003CD2 66D1EE              <1> 	shr	si, 1
  2796                              <1> 		; asr r1 / set up index to p.stat
  2797 00003CD5 8A86[F7710000]      <1> 	mov	al, [esi+p.stat-1]
  2798                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2799 00003CDB 20C0                <1> 	and	al, al
  2800 00003CDD 7424                <1> 	jz	short sysexit_6
  2801                              <1> 		; beq 2f / if its been freed, 2f
  2802 00003CDF 3C03                <1> 	cmp	al, 3
  2803                              <1> 		; cmp r2,$3 / is parent a zombie?
  2804 00003CE1 7420                <1> 	je	short sysexit_6
  2805                              <1> 		; beq 2f / yes, 2f
  2806                              <1> 	; BH = 0
  2807 00003CE3 8A1D[FD750000]      <1> 	mov	bl, [u.uno]
  2808                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2809 00003CE9 C683[F7710000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2810                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2811                              <1> 	; 05/02/2014
  2812 00003CF0 3C01                <1> 	cmp	al, 1 ; SRUN
  2813 00003CF2 740F                <1> 	je	short sysexit_6
  2814                              <1> 	;cmp	al, 2
  2815                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2816                              <1> 			  ; / this child to die
  2817                              <1> 	;jne	short sysexit_6	
  2818                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2819                              <1> 	; 05/02/2014
  2820                              <1> 	; p.stat = 2 --> waiting
  2821                              <1> 	; p.stat = 4 --> sleeping
  2822 00003CF4 C686[F7710000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2823                              <1> 	;dec	byte [esi+p.stat-1]
  2824                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2825 00003CFB 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2826                              <1> 	; 
  2827                              <1> 	;mov	ebx, runq + 4
  2828                              <1> 		; mov $runq+4,r2 / on the runq
  2829 00003CFE E86A130000          <1> 	call	putlu
  2830                              <1> 		; jsr r0, putlu
  2831                              <1> sysexit_6: ; 2:
  2832                              <1> 	; 31/08/2015
  2833                              <1> 		; / the process dies
  2834 00003D03 C605[FD750000]00    <1> 	mov	byte [u.uno], 0
  2835                              <1> 		; clrb u.uno / put zero as the process number, 
  2836                              <1> 	           ; / so "swap" will
  2837 00003D0A E891120000          <1> 	call	swap
  2838                              <1> 		; jsr r0,swap / overwrite process with another process
  2839                              <1> hlt_sys:
  2840                              <1> 	;sti ; 18/01/2014
  2841                              <1> hlts0:
  2842 00003D0F F4                  <1> 	hlt
  2843 00003D10 EBFD                <1> 	jmp	short hlts0
  2844                              <1> 		; 0 / and thereby kill it; halt?
  2845                              <1> 
  2846                              <1> syswait: ; < wait for a processs to die >
  2847                              <1> 	; 09/02/2022
  2848                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2849                              <1> 	; 17/09/2015
  2850                              <1> 	; 02/09/2015
  2851                              <1> 	; 01/09/2015
  2852                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2853                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2854                              <1> 	;
  2855                              <1> 	; 'syswait' waits for a process die. 
  2856                              <1> 	; It works in following way:
  2857                              <1> 	;    1) From the parent process number, the parent's 
  2858                              <1> 	; 	process name is found. The p.ppid table of parent
  2859                              <1> 	;	names is then searched for this process name.
  2860                              <1> 	;	If a match occurs, r2 contains child's process
  2861                              <1> 	;	number. The child status is checked to see if it is
  2862                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2863                              <1> 	;	If it is, the child process is freed and it's name
  2864                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2865                              <1> 	;	If the child is not a zombie, nothing happens and
  2866                              <1> 	;	the search goes on through the p.ppid table until
  2867                              <1> 	;	all processes are checked or a zombie is found.
  2868                              <1> 	;    2) If no zombies are found, a check is made to see if
  2869                              <1> 	;	there are any children at all. If there are none,
  2870                              <1> 	;	an error return is made. If there are, the parent's
  2871                              <1> 	;	status is set to 2 (waiting for child to die),
  2872                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2873                              <1> 	;	is made to wait on the next process.
  2874                              <1> 	;
  2875                              <1> 	; Calling sequence:
  2876                              <1> 	;	?
  2877                              <1> 	; Arguments:
  2878                              <1> 	;	-
  2879                              <1> 	; Inputs: - 
  2880                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2881                              <1> 	; ...............................................................
  2882                              <1> 	;				
  2883                              <1> 	
  2884                              <1> ; / wait for a process to die
  2885                              <1> 
  2886                              <1> syswait_0:
  2887 00003D12 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2888                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2889 00003D19 D0E3                <1> 	shl	bl, 1
  2890                              <1> 	;shl	bx, 1
  2891                              <1> 		; asl r1 / x2 to get index into p.pid table
  2892 00003D1B 668B83[96710000]    <1> 	mov	ax, [ebx+p.pid-2]
  2893                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2894 00003D22 31F6                <1> 	xor	esi, esi
  2895                              <1> 		; clr r2
  2896 00003D24 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2897                              <1> 	;xor 	cl, cl
  2898                              <1> 		; clr r3 / initialize reg 3
  2899                              <1> syswait_1: ; 1:
  2900                              <1> 	; 09/02/2022
  2901 00003D26 46                  <1> 	inc	esi
  2902 00003D27 46                  <1> 	inc	esi
  2903                              <1> 	;add	si, 2
  2904                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2905                              <1> 			  ; / search table of parent processes 
  2906                              <1> 			  ; / for this process name
  2907 00003D28 663B86[B6710000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2908                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2909                              <1> 			            ; / process number
  2910 00003D2F 7531                <1> 	jne	short syswait_3
  2911                              <1> 		; bne 3f / branch if no match of parent process name
  2912                              <1> 	;inc	cx
  2913 00003D31 FEC1                <1> 	inc	cl
  2914                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2915                              <1> 	; 09/02/2022
  2916 00003D33 D1EE                <1> 	shr	esi, 1
  2917                              <1> 	;shr	si, 1
  2918                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2919                              <1> 	; The possible states ('p.stat' values) of a process are:
  2920                              <1> 	;	0 = free or unused
  2921                              <1> 	;	1 = active
  2922                              <1> 	;	2 = waiting for a child process to die
  2923                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2924 00003D35 80BE[F7710000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2925                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2926 00003D3C 7522                <1> 	jne	short syswait_2
  2927                              <1> 		; bne 2f / no, skip it
  2928 00003D3E 88BE[F7710000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2929                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2930                              <1> 	; 09/02/2022
  2931 00003D44 D1E6                <1> 	shl	esi, 1
  2932                              <1> 	;shl	si, 1
  2933                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2934 00003D46 0FB786[96710000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2935 00003D4D A3[AC750000]        <1> 	mov	[u.r0], eax
  2936                              <1> 		; mov p.pid-2(r2),*u.r0 
  2937                              <1> 			      ; / put childs process name in (u.r0)
  2938                              <1> 	;
  2939                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2940                              <1> 	;
  2941                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2942                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2943                              <1> 	; system call loop from the application/program if it calls
  2944                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2945                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2946                              <1> 	;
  2947                              <1> 	; Note: syswait will return with error if there is not a
  2948                              <1> 	;       zombie or running process to wait.	
  2949                              <1> 	;
  2950                              <1> 	;sub	ax, ax
  2951                              <1> 	; 08/01/2022
  2952 00003D52 29C0                <1> 	sub	eax, eax
  2953 00003D54 668986[B6710000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2954 00003D5B E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2955                              <1> 	;
  2956                              <1> 	;jmp	sysret
  2957                              <1> 		; br sysret1 / return cause child is dead
  2958                              <1> syswait_2: ; 2:
  2959                              <1> 	; 09/02/2022
  2960 00003D60 D1E6                <1> 	shl	esi, 1
  2961                              <1> 	;shl	si, 1
  2962                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2963                              <1> syswait_3: ; 3:
  2964 00003D62 6683FE20            <1> 	cmp	si, nproc+nproc
  2965                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2966 00003D66 72BE                <1> 	jb	short syswait_1
  2967                              <1> 		; blt 1b / no, continue search
  2968                              <1> 	;and	cx, cx
  2969 00003D68 20C9                <1> 	and	cl, cl
  2970                              <1> 		; tst r3 / one gets here if there are no children 
  2971                              <1> 		       ; / or children that are still active
  2972                              <1> 	; 30/10/2013
  2973 00003D6A 7515                <1> 	jnz	short syswait_4
  2974                              <1> 	;jz	error
  2975                              <1> 		; beq error1 / there are no children, error
  2976 00003D6C 890D[AC750000]      <1> 	mov	[u.r0], ecx ; 0
  2977                              <1> 	; 09/02/2022
  2978 00003D72 C705[20760000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2978 00003D7A 0000                <1>
  2979                              <1> 			; miscellaneous/other errors
  2980 00003D7C E9C7FDFFFF          <1> 	jmp	error
  2981                              <1> syswait_4:
  2982 00003D81 8A1D[FD750000]      <1> 	mov	bl, [u.uno]
  2983                              <1> 		; movb u.uno,r1 / there are children so put 
  2984                              <1> 			      ; / parent process number in r1
  2985 00003D87 FE83[F7710000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2986                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2987                              <1> 				  ; / other children to die
  2988                              <1> 	; 04/11/2013
  2989 00003D8D E80E120000          <1> 	call	swap
  2990                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2991 00003D92 E97BFFFFFF          <1> 	jmp	syswait_0
  2992                              <1> 		; br syswait / wait on next process
  2993                              <1> 
  2994                              <1> sysfork: ; < create a new process >
  2995                              <1> 	; 27/02/2022
  2996                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2997                              <1> 	; 18/09/2015
  2998                              <1> 	; 04/09/2015
  2999                              <1> 	; 02/09/2015
  3000                              <1> 	; 01/09/2015
  3001                              <1> 	; 28/08/2015
  3002                              <1> 	; 14/05/2015
  3003                              <1> 	; 10/05/2015
  3004                              <1> 	; 09/05/2015
  3005                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3006                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3007                              <1> 	;
  3008                              <1> 	; 'sysfork' creates a new process. This process is referred
  3009                              <1> 	; to as the child process. This new process core image is
  3010                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3011                              <1> 	; distinction is the return location and the fact that (u.r0)
  3012                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3013                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3014                              <1> 	; 'sysfork' works in the following manner: 	
  3015                              <1> 	;    1) The process status table (p.stat) is searched to find
  3016                              <1> 	;	a process number that is unused. If none are found
  3017                              <1> 	;	an error occurs.
  3018                              <1> 	;    2) when one is found, it becomes the child process number
  3019                              <1> 	;	and it's status (p.stat) is set to active.
  3020                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3021                              <1> 	;	character in that tty buffer is cleared.
  3022                              <1> 	;    4) The child process is put on the lowest priority run 
  3023                              <1> 	;	queue via 'putlu'.
  3024                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3025                              <1> 	;	it is a unique number) and is put in the child's unique
  3026                              <1> 	;	identifier; process id (p.pid).
  3027                              <1> 	;    6) The process name of the parent is then obtained and
  3028                              <1> 	;	placed in the unique identifier of the parent process
  3029                              <1> 	;	name is then put in 'u.r0'.	
  3030                              <1> 	;    7) The child process is then written out on disk by
  3031                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3032                              <1> 	;	and the child is born. (The child process is written 
  3033                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3034                              <1> 	;	number.)
  3035                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3036                              <1> 	;    9) The child process name is put in 'u.r0'.
  3037                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3038                              <1> 	;	create the return address for the parent process.
  3039                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3040                              <1> 	;	the parent has opened. For each file the parent has
  3041                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3042                              <1> 	;	to indicate that the child process also has opened
  3043                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3044                              <1> 	;
  3045                              <1> 	; Calling sequence:
  3046                              <1> 	;	from shell ?
  3047                              <1> 	; Arguments:
  3048                              <1> 	;	-
  3049                              <1> 	; Inputs: -
  3050                              <1> 	; Outputs: *u.r0 - child process name
  3051                              <1> 	; ...............................................................
  3052                              <1> 	;	
  3053                              <1> 	; Retro UNIX 8086 v1 modification: 
  3054                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3055                              <1> 	;	= process id of child a parent process returns
  3056                              <1> 	;	= process id of parent when a child process returns
  3057                              <1> 	;
  3058                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3059                              <1> 	;	in following manner: (with an example: c library, fork)
  3060                              <1> 	;	
  3061                              <1> 	;	1:
  3062                              <1> 	;		sys	fork
  3063                              <1> 	;			br 1f  / child process returns here
  3064                              <1> 	;		bes	2f     / parent process returns here
  3065                              <1> 	;		/ pid of new process in r0
  3066                              <1> 	;		rts	pc
  3067                              <1> 	;	2: / parent process condionally branches here
  3068                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3069                              <1> 	;		rts	pc
  3070                              <1> 	;
  3071                              <1> 	;	1: / child process brances here
  3072                              <1> 	;		clr	r0   / pid = 0 in child process
  3073                              <1> 	;		rts	pc
  3074                              <1> 	;
  3075                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3076                              <1> 	;		// pid = fork();
  3077                              <1> 	;		//
  3078                              <1> 	;		// pid == 0 in child process; 
  3079                              <1> 	;		// pid == -1 means error return
  3080                              <1> 	;		// in child, 
  3081                              <1> 	;		//	parents id is in par_uid if needed
  3082                              <1> 	;		
  3083                              <1> 	;		_fork:
  3084                              <1> 	;			mov	$.fork,eax
  3085                              <1> 	;			int	$0x30
  3086                              <1> 	;			jmp	1f
  3087                              <1> 	;			jnc	2f
  3088                              <1> 	;			jmp	cerror
  3089                              <1> 	;		1:
  3090                              <1> 	;			mov	eax,_par_uid
  3091                              <1> 	;			xor	eax,eax
  3092                              <1> 	;		2:
  3093                              <1> 	;			ret
  3094                              <1> 	;
  3095                              <1> 	;	In Retro UNIX 8086 v1,
  3096                              <1> 	;	'sysfork' returns in following manner:
  3097                              <1> 	;	
  3098                              <1> 	;		mov	ax, sys_fork
  3099                              <1> 	;		mov	bx, offset @f ; routine for child
  3100                              <1> 	;		int	20h
  3101                              <1> 	;		jc	error
  3102                              <1> 	;		
  3103                              <1> 	;	; Routine for parent process here (just after 'jc')
  3104                              <1> 	;		mov	word ptr [pid_of_child], ax
  3105                              <1> 	;		jmp	next_routine_for_parent	
  3106                              <1> 	;
  3107                              <1> 	;	@@: ; routine for child process here				
  3108                              <1> 	;		....	
  3109                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3110                              <1> 	;	       for child process by using BX input.
  3111                              <1> 	;	      (at first, parent process will return then 
  3112                              <1> 	;	      child process will return -after swapped in-
  3113                              <1> 	;	      'syswait' is needed in parent process
  3114                              <1> 	;	      if return from child process will be waited for.)
  3115                              <1> 	;	  				
  3116                              <1> 	
  3117                              <1> ; / create a new process
  3118                              <1> 	; EBX = return address for child process 
  3119                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3120 00003D97 31F6                <1> 	xor 	esi, esi
  3121                              <1> 		; clr r1
  3122                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3123 00003D99 46                  <1> 	inc	esi
  3124                              <1> 		; inc r1
  3125 00003D9A 80BE[F7710000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3126                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3127 00003DA1 760B                <1> 	jna	short sysfork_2	
  3128                              <1> 		; beq 1f / it's unused so branch
  3129 00003DA3 6683FE10            <1> 	cmp	si, nproc
  3130                              <1> 		; cmp r1,$nproc / all processes checked
  3131 00003DA7 72F0                <1> 	jb	short sysfork_1
  3132                              <1> 		; blt 1b / no, branch back
  3133                              <1> 	;
  3134                              <1> 	; Retro UNIX 8086 v1. modification:
  3135                              <1> 	;	Parent process returns from 'sysfork' to address 
  3136                              <1> 	;	which is just after 'sysfork' system call in parent
  3137                              <1> 	;	process. Child process returns to address which is put
  3138                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3139                              <1> 	;
  3140                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3141                              <1> 		             ; / to old process return
  3142                              <1> 		; br error1 / no room for a new process
  3143                              <1> sysfork_0:
  3144 00003DA9 E99AFDFFFF          <1> 	jmp	error
  3145                              <1> sysfork_2: ; 1:
  3146 00003DAE E801F0FFFF          <1> 	call	allocate_page
  3147                              <1> 	;jc	error
  3148                              <1> 	; 08/01/2022
  3149 00003DB3 72F4                <1> 	jc	short sysfork_0
  3150                              <1> 
  3151 00003DB5 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3152                              <1> 	; Retro UNIX 386 v1 modification!
  3153 00003DB6 E8F2F1FFFF          <1> 	call	duplicate_page_dir
  3154                              <1> 		; EAX = New page directory 
  3155 00003DBB 7308                <1> 	jnc	short sysfork_3
  3156 00003DBD 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3157 00003DBE E8B9F1FFFF          <1> 	call 	deallocate_page
  3158                              <1> 	;jmp	error
  3159                              <1> 	; 08/01/2022
  3160 00003DC3 EBE4                <1> 	jmp	short sysfork_0  ; error
  3161                              <1> sysfork_3:
  3162                              <1> 	; Retro UNIX 386 v1 modification !
  3163 00003DC5 56                  <1> 	push	esi
  3164 00003DC6 E84C120000          <1> 	call	wswap ; save current user (u) structure, user registers
  3165                              <1> 		      ; and interrupt return components (for IRET)
  3166 00003DCB 8705[0C760000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3167 00003DD1 A3[10760000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3168 00003DD6 5E                  <1> 	pop	esi
  3169 00003DD7 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3170                              <1> 		; [u.usp] = esp
  3171 00003DD8 89F7                <1> 	mov	edi, esi
  3172                              <1> 	;shl	di, 2
  3173                              <1> 	; 08/01/2022
  3174 00003DDA C1E702              <1> 	shl	edi, 2
  3175 00003DDD 8987[04720000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3176 00003DE3 A3[08760000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3177                              <1> 	; 28/08/2015
  3178 00003DE8 0FB605[FD750000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3179                              <1> 		; movb u.uno,-(sp) / save parent process number
  3180 00003DEF 89C7                <1> 	mov	edi, eax
  3181 00003DF1 50                  <1>         push	eax ; ** 
  3182 00003DF2 8A87[D7710000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3183                              <1> 	; 18/09/2015 (27/02/2022)
  3184 00003DF8 8886[D7710000]      <1> 	mov	[esi+p.ttyc-1], al ; set child's console tty
  3185                              <1> 	; 27/02/2022 (p.waitc is not used)
  3186                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3187                              <1> 	; 27/02/2022 (BugFix)
  3188                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3189                              <1> 	;			   ; ah - reset child's wait channel
  3190 00003DFE 89F0                <1> 	mov	eax, esi
  3191 00003E00 A2[FD750000]        <1> 	mov	[u.uno], al ; child process number
  3192                              <1> 		;movb r1,u.uno / set child process number to r1
  3193 00003E05 FE86[F7710000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3194                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3195                              <1> 				; / process to active status
  3196                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3197                              <1> 			      ; / control tty buffer in r2
  3198                              <1>                 ; beq 2f / branch, if no such tty assigned
  3199                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3200                              <1> 	; 2:
  3201 00003E0B 53                  <1> 	push	ebx  ; * return address for the child process
  3202                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3203                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3204                              <1> 		; mov $runq+4,r2
  3205 00003E0C E85C120000          <1> 	call	putlu 
  3206                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3207                              <1> 			   ; / run queue
  3208                              <1> 	; 08/01/2022
  3209 00003E11 D1E6                <1> 	shl	esi, 1
  3210                              <1> 	;shl	si, 1
  3211                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3212                              <1> 		       ; / into p.pid table
  3213 00003E13 66FF05[92750000]    <1> 	inc	word [mpid]
  3214                              <1> 		; inc mpid / increment m.pid; get a new process name
  3215 00003E1A 66A1[92750000]      <1> 	mov	ax, [mpid]
  3216 00003E20 668986[96710000]    <1> 	mov	[esi+p.pid-2], ax
  3217                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3218                              <1> 				    ; / in child process' name slot
  3219 00003E27 5A                  <1> 	pop	edx  ; * return address for the child process
  3220                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3221 00003E28 5B                  <1>   	pop	ebx  ; **
  3222                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3223                              <1> 		; movb (sp),r2 / put parent process number in r2
  3224                              <1> 	; 08/01/2022
  3225 00003E29 D1E3                <1> 	shl	ebx, 1
  3226                              <1> 	;shl 	bx, 1
  3227                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3228                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3229 00003E2B 668B83[96710000]    <1> 	mov	ax, [ebx+p.pid-2]
  3230                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3231                              <1> 				   ; / process
  3232 00003E32 668986[B6710000]    <1> 	mov	[esi+p.ppid-2], ax
  3233                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3234                              <1> 			  ; / in parent process slot for child
  3235 00003E39 A3[AC750000]        <1> 	mov	[u.r0], eax	
  3236                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3237                              <1> 			     ; / at location where r0 was saved
  3238 00003E3E 8B2D[A4750000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3239 00003E44 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3240                              <1> 			   ; * return address for the child process
  3241                              <1> 		; mov $sysret1,-(sp) /
  3242                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3243                              <1> 			      ; / user is swapped out
  3244                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3245                              <1> 	; 04/09/2015 - 01/09/2015
  3246                              <1> 	; [u.usp] = esp
  3247 00003E47 68[683B0000]        <1> 	push	sysret ; ***
  3248 00003E4C 8925[A8750000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3249                              <1> 			     ; (for child process)	
  3250 00003E52 31C0                <1> 	xor 	eax, eax
  3251 00003E54 66A3[E2750000]      <1> 	mov 	[u.ttyp], ax ; 0
  3252                              <1> 	;
  3253 00003E5A E8B8110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3254                              <1> 		;jsr r0,wswap / put child process out on drum
  3255                              <1> 		;jsr r0,unpack / unpack user stack
  3256                              <1> 		;mov u.usp,sp / restore user stack pointer
  3257                              <1> 		; tst (sp)+ / bump stack pointer
  3258                              <1> 	; Retro UNIX 386 v1 modification !
  3259 00003E5F 58                  <1> 	pop	eax ; ***
  3260                              <1> 	; 08/01/2022
  3261 00003E60 D1E3                <1> 	shl	ebx, 1
  3262                              <1> 	;shl 	bx, 1
  3263 00003E62 8B83[04720000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3264 00003E68 E8D3110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3265                              <1> 		      ; registers and return address (for IRET)
  3266                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3267 00003E6D 0FB705[92750000]    <1>         movzx   eax, word [mpid]
  3268 00003E74 A3[AC750000]        <1> 	mov	[u.r0], eax
  3269                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3270                              <1> 			       ; / where r0 was saved
  3271                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3272                              <1> 			          ; / process return
  3273                              <1> 	;xor	ebx, ebx
  3274 00003E79 31F6                <1> 	xor     esi, esi
  3275                              <1> 		;clr r1
  3276                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3277                              <1> 	      ; / opened by the parent process
  3278                              <1> 	; 08/01/2022
  3279                              <1> 	; 01/09/2015
  3280 00003E7B 30FF                <1> 	xor	bh, bh
  3281 00003E7D 8A9E[B6750000]      <1> 	mov 	bl, [esi+u.fp]
  3282                              <1> 	; 08/01/2022
  3283                              <1> 	;mov 	al, [esi+u.fp]
  3284                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3285 00003E83 08DB                <1> 	or	bl, bl
  3286                              <1> 	; 08/01/2022
  3287                              <1> 	;or	al, al
  3288 00003E85 7409                <1> 	jz	short sysfork_5	
  3289                              <1> 		; beq 2f / file has not been opened by parent, 
  3290                              <1> 		       ; / so branch
  3291                              <1> 	;mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3292                              <1> 	; 08/01/2022
  3293                              <1> 	;mov	ah, 16 ; Retro UNIX 386 v2 fsp structure size = 16 bytes
  3294                              <1> 	;mul	ah
  3295                              <1> 	;;movzx	ebx, ax
  3296                              <1> 	;mov	bx, ax
  3297                              <1> 	;mov	ebx, eax ; 08/01/2022
  3298                              <1> 	;shl	bx, 3
  3299                              <1> 		; asl r2 / multiply by 8
  3300                              <1>        		; asl r2 / to get index into fsp table
  3301                              <1>        		; asl r2
  3302                              <1> 	; 08/01/2022
  3303 00003E87 C1E304              <1> 	shl	ebx, 4 ; multiply by 16
  3304                              <1> 	; 08/01/2022
  3305 00003E8A FE83[3E720000]      <1> 	inc	byte [ebx+fsp-10] ; Retro UNIX 386 v2 fs fsp structure
  3306                              <1>   	;inc	byte [ebx+fsp-2]
  3307                              <1> 		; incb fsp-2(r2) / increment number of processes
  3308                              <1> 			     ; / using file, because child will now be
  3309                              <1> 			     ; / using this file
  3310                              <1> sysfork_5: ; 2:
  3311 00003E90 46                  <1>         inc     esi
  3312                              <1> 		; inc r1 / get next open file
  3313 00003E91 6683FE0A            <1>         cmp     si, 10
  3314                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3315                              <1> 			  ; / can be opened
  3316 00003E95 72E4                <1> 	jb	short sysfork_4	
  3317                              <1> 		; blt 1b / check next entry
  3318 00003E97 E9CCFCFFFF          <1> 	jmp	sysret
  3319                              <1> 		; br sysret1
  3320                              <1> 
  3321                              <1> sysread: ; < read from file >
  3322                              <1> 	; 24/12/2021
  3323                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3324                              <1> 	; 27/03/2020
  3325                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3326                              <1> 	; 13/05/2015
  3327                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3328                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3329                              <1> 	;
  3330                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3331                              <1> 	; characters to be read. If finds the file from the file
  3332                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3333                              <1> 	; is returned from a successful open call (sysopen).
  3334                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3335                              <1> 	; is read into core via 'readi'.
  3336                              <1> 	;
  3337                              <1> 	; Calling sequence:
  3338                              <1> 	;	sysread; buffer; nchars
  3339                              <1> 	; Arguments:
  3340                              <1> 	;	buffer - location of contiguous bytes where 
  3341                              <1> 	;		 input will be placed.
  3342                              <1> 	;	nchars - number of bytes or characters to be read.
  3343                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3344                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3345                              <1> 	; ...............................................................
  3346                              <1> 	;				
  3347                              <1> 	; Retro UNIX 8086 v1 modification: 
  3348                              <1> 	;       'sysread' system call has three arguments; so,
  3349                              <1> 	;	* 1st argument, file descriptor is in BX register
  3350                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3351                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3352                              <1> 	;
  3353                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3354                              <1> 	;	to the user with number of bytes read. 
  3355                              <1> 	;
  3356                              <1> 
  3357 00003E9C E839000000          <1> 	call	rw1
  3358                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3359                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3360                              <1>        	; 04/12/2021
  3361 00003EA1 7209                <1> 	jc	short sysread_err
  3362 00003EA3 7529                <1> 	jnz	short rw3 ; error ! (permission denied)
  3363                              <1> 	;		; read a file while it is open for write!
  3364                              <1> 
  3365                              <1> 	; eax = inode number
  3366                              <1> 
  3367                              <1> 	; 04/12/2021
  3368                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3369                              <1> 	;test	ah, 80h
  3370                              <1> 	;	; tst r1 / negative i-number?
  3371                              <1> 	;;jnz	error
  3372                              <1> 	;;	; ble error1 / yes, error 1 to read
  3373                              <1> 	;;		   ; / it should be positive
  3374                              <1> 	;; 04/12/2021
  3375                              <1> 	;jnz	short sysread_err
  3376                              <1> 
  3377 00003EA5 E8D7190000          <1> 	call	readi
  3378                              <1> 		; jsr r0,readi / read data into core
  3379 00003EAA EB13                <1> 	jmp	short rw0
  3380                              <1> 		; br 1f
  3381                              <1> sysread_err:
  3382                              <1> syswrite_err:
  3383                              <1> 	; 04/12/2021
  3384 00003EAC E997FCFFFF          <1> 	jmp	error
  3385                              <1> 
  3386                              <1> syswrite: ; < write to file >
  3387                              <1> 	; 24/12/2021
  3388                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3389                              <1> 	; 27/03/2020
  3390                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3391                              <1> 	; 13/05/2015
  3392                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3393                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3394                              <1> 	;
  3395                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3396                              <1> 	; and the number of characters to write. If finds the file
  3397                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3398                              <1> 	; descriptor is returned from a successful open or create call
  3399                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3400                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3401                              <1> 	;
  3402                              <1> 	; Calling sequence:
  3403                              <1> 	;	syswrite; buffer; nchars
  3404                              <1> 	; Arguments:
  3405                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3406                              <1> 	;	nchars - number of characters to be written.
  3407                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3408                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3409                              <1> 	; ...............................................................
  3410                              <1> 	;				
  3411                              <1> 	; Retro UNIX 8086 v1 modification: 
  3412                              <1> 	;       'syswrite' system call has three arguments; so,
  3413                              <1> 	;	* 1st argument, file descriptor is in BX register
  3414                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3415                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3416                              <1> 	;
  3417                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3418                              <1> 	;	to the user with number of bytes written. 
  3419                              <1> 	;
  3420                              <1> 
  3421 00003EB1 E824000000          <1> 	call	rw1
  3422                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3423                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3424                              <1>        	; 04/12/2021
  3425 00003EB6 72F4                <1> 	jc	short syswrite_err
  3426 00003EB8 7414                <1> 	jz	short rw3 ; error ! (permission denied)
  3427                              <1> 			; write to a file while it is open for read
  3428                              <1> 	; eax = inode number
  3429                              <1> 	
  3430                              <1> 	; 04/12/2021
  3431                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3432                              <1> 	;test	ah, 80h
  3433                              <1> 	;	; tst r1 / positive i-number ?
  3434                              <1>         ;jz	short rw3 ; 13/05/2015
  3435                              <1> 	;;jz	error
  3436                              <1> 	;	; bge error1 / yes, error 1 
  3437                              <1> 	;		   ; / negative i-number means write
  3438                              <1>         ;neg	ax
  3439                              <1> 	;	; neg r1 / make it positive
  3440                              <1> 	
  3441 00003EBA E8D21B0000          <1> 	call	writei
  3442                              <1>         	; jsr r0,writei / write data
  3443                              <1> rw0: ; 1:
  3444 00003EBF A1[D8750000]        <1>         mov	eax, [u.nread]
  3445 00003EC4 A3[AC750000]        <1> 	mov	[u.r0], eax
  3446                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3447                              <1> 				  ; / into (u.r0)
  3448 00003EC9 E99AFCFFFF          <1> 	jmp	sysret
  3449                              <1>         	; br sysret1
  3450                              <1> rw3: 
  3451                              <1> 	; 13/05/2015
  3452 00003ECE C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3452 00003ED6 0000                <1>
  3453                              <1> 	;stc
  3454                              <1> 	;retn
  3455                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.2
  3456 00003ED8 EBD2                <1> 	jmp	short syswrite_err
  3457                              <1> 
  3458                              <1> rw1:	
  3459                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3460                              <1> 	; 27/03/2020
  3461                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3462                              <1> 	; 14/05/2015
  3463                              <1> 	; 13/05/2015
  3464                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3465                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3466                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3467                              <1> 	;
  3468                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3469                              <1> 				;(in the user's virtual memory space)
  3470                              <1> 	;mov	[u.count], edx 
  3471                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3472                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3473                              <1> 	;;mov	eax, ebx ; file descriptor
  3474                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3475                              <1> 		             ; / (index to u.fp table) in r1
  3476                              <1> 	; 13/05/2015
  3477 00003EDA C705[AC750000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3477 00003EE2 0000                <1>
  3478                              <1> 	;
  3479                              <1> 	;; call	getf
  3480                              <1>         ; ebx = File descriptor
  3481 00003EE4 E8390B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3482                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3483                              <1> 	; AX = I-number of the file ; negative i-number means write
  3484                              <1> 
  3485                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3486                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3487                              <1> 	; BL = open mode & status flag (0 = read, 1 = write)
  3488                              <1> 	; eax = inode number (ax)
  3489                              <1> 	; 27/03/2020
  3490                              <1> 	; [cdev] = logical drive number 	
  3491                              <1> 
  3492                              <1> 	; 13/05/2015
  3493 00003EE9 6683F801            <1> 	cmp 	ax, 1
  3494 00003EED 721A                <1> 	jb	short rw2
  3495                              <1> 	;
  3496 00003EEF 890D[D0750000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3497                              <1> 				;(in the user's virtual memory space)
  3498 00003EF5 8915[D4750000]      <1> 	mov	[u.count], edx 
  3499                              <1> 	; 14/05/2015
  3500 00003EFB C705[20760000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3500 00003F03 0000                <1>
  3501                              <1> 
  3502                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3503                              <1> 	; 27/03/2020 - Retro UNIX 386 v2
  3504 00003F05 80E301              <1> 	and	bl, 1
  3505                              <1> 		; zf = 0 -> open for write	
  3506                              <1> 		; zf = 1 -> open for read
  3507 00003F08 C3                  <1> 	retn
  3508                              <1>         	; rts r0
  3509                              <1> rw2:
  3510                              <1> 	; 13/05/2015
  3511 00003F09 C705[20760000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3511 00003F11 0000                <1>
  3512 00003F13 C3                  <1> 	retn
  3513                              <1> 
  3514                              <1> 	; 08/01/2022
  3515                              <1> 	; 02/01/2022
  3516                              <1> 	; 01/01/2022
  3517                              <1> 	; 27/12/2021
  3518                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility code
  3519                              <1> sysopen: ;<open file>
  3520                              <1> 	; 04/12/2021
  3521                              <1> 	; 07/08/2020 (Retro UNIX 386 v2)
  3522                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3523                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3524                              <1> 	;
  3525                              <1> 	; 'sysopen' opens a file in following manner:
  3526                              <1> 	;    1) The second argument in a sysopen says whether to
  3527                              <1> 	;	open the file ro read (0) or write (>0).
  3528                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3529                              <1> 	;    3) The file is opened by 'iopen'.
  3530                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3531                              <1> 	;	and the user's open file list - u.fp.
  3532                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3533                              <1> 	;	b) An entry for the file is created in the fsp table.
  3534                              <1> 	;	c) The number of this entry is put on u.fp list.
  3535                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3536                              <1> 	;	   to by u.r0.
  3537                              <1> 	;
  3538                              <1> 	; Calling sequence:
  3539                              <1> 	;	sysopen; name; mode
  3540                              <1> 	; Arguments:
  3541                              <1> 	;	name - file name or path name
  3542                              <1> 	;	mode - 0 to open for reading
  3543                              <1> 	;	       1 to open for writing
  3544                              <1> 	; Inputs: (arguments)
  3545                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3546                              <1> 	;		  is put into r0's location on the stack.	
  3547                              <1> 	; ...............................................................
  3548                              <1> 	;				
  3549                              <1> 	; Retro UNIX 8086 v1 modification: 
  3550                              <1> 	;       'sysopen' system call has two arguments; so,
  3551                              <1> 	;	* 1st argument, name is pointed to by BX register
  3552                              <1> 	;	* 2nd argument, mode is in CX register
  3553                              <1> 	;
  3554                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3555                              <1> 	;	to the user with the file descriptor/number 
  3556                              <1> 	;	(index to u.fp list).
  3557                              <1> 	;
  3558                              <1> 	;call	arg2
  3559                              <1> 	; * name - 'u.namep' points to address of file/path name
  3560                              <1> 	;          in the user's program segment ('u.segmnt')
  3561                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3562                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3563                              <1> 	;          which is on top of stack.
  3564                              <1> 	;
  3565                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3566                              <1> 	;
  3567                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3568                              <1> 
  3569 00003F14 891D[C8750000]      <1> 	mov	[u.namep], ebx
  3570 00003F1A 51                  <1> 	push	ecx ; * ; 04/12/2021 (cx -> ecx)
  3571 00003F1B E8380B0000          <1> 	call	namei
  3572                              <1> 		; jsr r0,namei / i-number of file in r1
  3573                              <1>      	;and	ax, ax
  3574                              <1> 	;jz	error ; File not found
  3575 00003F20 722B                <1> 	jc	short fnotfound ; 14/05/2015
  3576                              <1> 	;jc	error ; 27/05/2013
  3577                              <1> 		; br  error2 / file not found
  3578                              <1>    	;pop	edx ; * ; mode ; 04/12/2021
  3579                              <1> 	;push	edx ; *
  3580                              <1> 	;;or	dx, dx
  3581                              <1> 	;or	dl, dl
  3582                              <1> 	;	; tst (sp) / is mode = 0 (2nd arg of call;
  3583                              <1> 	;	         ; / 0 means, open for read)
  3584                              <1> 	;;jz	short sysopen_0
  3585                              <1> 	;;	; beq 1f / yes, leave i-number positive
  3586                              <1> 	
  3587 00003F22 8B1424              <1> 	mov	edx, [esp] ; *
  3588                              <1> 	; edx = open mode (0 or 1)
  3589                              <1> 
  3590                              <1> ;syscreat_0: ;op0: ; 27/12/2015
  3591                              <1> ;	neg	ax
  3592                              <1> ;        	; neg r1 / open for writing so make i-number negative
  3593                              <1> 
  3594                              <1> sysopen_0: ;1:
  3595 00003F25 E84B1F0000          <1> 	call	iopen
  3596                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3597 00003F2A 5A                  <1> 	pop	edx ; * ; mode ; 04/12/2021
  3598                              <1> 	;;and	dx, dx
  3599                              <1> 	;and	dl, dl
  3600                              <1>         ;	; tst (sp)+ / pop the stack and test the mode
  3601                              <1> 	;jz	short sysopen_2
  3602                              <1>         ;	; beq op1 / is open for read op1
  3603                              <1> ;sysopen_1: ;op0:
  3604                              <1> 	;neg	ax
  3605                              <1>         ;	; neg r1 
  3606                              <1> 	;	     ;/ make i-number positive if open for writing [???]
  3607                              <1> 
  3608                              <1> 	;; NOTE: iopen always make i-number positive.
  3609                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3610                              <1> sysopen_1: ; 04/12/2021
  3611                              <1> sysopen_2: ;op1:
  3612 00003F2B 31F6                <1>         xor     esi, esi
  3613                              <1>         	; clr r2 / clear registers
  3614 00003F2D 31DB                <1>         xor     ebx, ebx
  3615                              <1> 		; clr r3
  3616                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3617 00003F2F 389E[B6750000]      <1>         cmp     [esi+u.fp], bl ; 0
  3618                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3619 00003F35 7625                <1> 	jna	short sysopen_4
  3620                              <1> 		; beq 1f / if byte in list is 0 branch
  3621 00003F37 46                  <1>         inc     esi
  3622                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3623                              <1> 	; 02/01/2022
  3624                              <1> 	;cmp	si, OPENFILES ; 04/12/2021
  3625 00003F38 6683FE0A            <1> 	cmp	si, 10
  3626                              <1> 		; cmp r2,$10. / reached end of list?
  3627 00003F3C 72F1                <1> 	jb	short sysopen_3
  3628                              <1> 		; blt 1b / no, go back
  3629                              <1> toomanyf:
  3630                              <1> 	; 14/05/2015
  3631 00003F3E C705[20760000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3631 00003F46 0000                <1>
  3632 00003F48 E9FBFBFFFF          <1> 	jmp	error
  3633                              <1>         	; br error2 / yes, error (no files open)
  3634                              <1> fnotfound: 
  3635                              <1> 	; 14/05/2015
  3636 00003F4D C705[20760000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3636 00003F55 0000                <1>
  3637 00003F57 E9ECFBFFFF          <1> 	jmp	error
  3638                              <1> 
  3639                              <1> sysopen_4: ; 1:
  3640 00003F5C 6683BB[48720000]00  <1>         cmp     word [ebx+fsp], 0
  3641                              <1> 		; tst fsp(r3) / scan fsp entries
  3642 00003F64 760D                <1>         jna     short sysopen_5
  3643                              <1> 		; beq 1f / if 0 branch
  3644                              <1> 	;; 14/05/2015 - Retro UNIX 386 v1 modification !
  3645                              <1> 	;add	bx, 10 ; fsp structure size = 10 bytes/entry
  3646                              <1> 		; add $8.,r3 / add 8 to r3 
  3647                              <1> 			; / to bump it to next entry mfsp table
  3648                              <1> 	; 01/01/2022
  3649                              <1> 	; 07/08/2020 - Retro UNIX 386 v2
  3650 00003F66 6683C310            <1> 	add	bx, 16 ; fsp structure size = 16 bytes/entry ; runix v2
  3651                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  3652                              <1> 	;add	bx, fp.size
  3653                              <1> 
  3654                              <1> 	; 22/11/2021
  3655                              <1> 	;cmp	bx, NFILES*fp.size ; NFILES*16
  3656                              <1> 	; 02/01/2022
  3657 00003F6A 6681FB2003          <1> 	cmp	bx, nfiles*16
  3658                              <1> 	; 01/01/2022
  3659                              <1> 	;cmp	bx, NFILES*16 ; NFILES*fp.size
  3660                              <1> 	;;cmp	bx, nfiles*10
  3661                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3662 00003F6F 72EB                <1> 	jb	short sysopen_4
  3663                              <1>        		; blt 1b / no, back
  3664                              <1> 	;jmp	error
  3665                              <1>         ;	; br error2 / yes, error
  3666                              <1> 	; 04/12/2021
  3667                              <1> 	; 07/08/2020
  3668 00003F71 EBCB                <1> 	jmp	short toomanyf
  3669                              <1> 
  3670                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3671 00003F73 668983[48720000]    <1>         mov     [ebx+fsp], ax
  3672                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3673                              <1> 			; / into next available entry in fsp table,
  3674                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3675                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3676                              <1> 	;	; mov cdev,fsp+2(r3) / put # of device in next word
  3677                              <1> 
  3678                              <1> 	; 04/12/2021        
  3679 00003F7A A0[8D750000]        <1> 	mov	al, [cdev]
  3680 00003F7F 88D4                <1> 	mov	ah, dl ; open mode, 0 = read, 1 = write
  3681 00003F81 668983[4C720000]    <1> 	mov	[ebx+fsp+4], ax ; device number & open mode
  3682                              <1> 
  3683                              <1> 	;xor	edi, edi
  3684                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3685                              <1> 	;	; clr fsp+4(r3)
  3686                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3687                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3688                              <1> 
  3689                              <1> 	; 04/12/2021 
  3690 00003F88 31C0                <1> 	xor	eax, eax
  3691 00003F8A 8983[50720000]      <1>   	mov	[ebx+fsp+8], eax ; offset pointer = 0
  3692                              <1> 	;inc	word [ebx+fsp+6]
  3693 00003F90 FE83[4E720000]      <1> 	inc	byte [ebx+fsp+6] ; open count = open count + 1	
  3694                              <1> 
  3695                              <1>   	;mov	eax, ebx
  3696                              <1> 	;mov	bl, 10
  3697                              <1> 	;div	bl 
  3698                              <1> 	;	; asr r3
  3699                              <1> 	;	; asr r3 / divide by 8 
  3700                              <1> 	;	; asr r3 ; / to get number of the fsp entry-1
  3701                              <1> 	;inc	al
  3702                              <1>         ;	; inc r3 / add 1 to get fsp entry number
  3703                              <1>         ;mov	[esi+u.fp], al
  3704                              <1> 	;	; movb r3,u.fp(r2) / move entry number into 
  3705                              <1> 			; / next available slot in u.fp list
  3706                              <1> 	; 04/12/2021
  3707 00003F96 C1EB04              <1> 	shr	ebx, 4	; / 16
  3708                              <1> 	;shr	bx, 4	; bx = fsp entry number (index)	
  3709                              <1> 			; bx <= 49 for current runix 386 version
  3710 00003F99 FEC3                <1> 	inc 	bl	; bl = 1 to 50
  3711 00003F9B 889E[B6750000]      <1> 	mov	[esi+u.fp], bl 	
  3712                              <1> 
  3713 00003FA1 8935[AC750000]      <1>         mov     [u.r0], esi
  3714                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3715                              <1> 			     ; / into r0 loc on stack
  3716 00003FA7 E9BCFBFFFF          <1>         jmp	sysret
  3717                              <1> 		; br sysret2
  3718                              <1> 
  3719                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  3720                              <1> ;
  3721                              <1> ;         15                    7                   0
  3722                              <1> ;  1     |-------------------------------------------|
  3723                              <1> ;        |   	     i-number of open file           |
  3724                              <1> ;        |-------------------------------------------| 
  3725                              <1> ;        |        high word of 32 bit i-number       |
  3726                              <1> ;        |-------------------------------------------|
  3727                              <1> ;        | open mode & status  |   device number     |
  3728                              <1> ;        |-------------------------------------------|			
  3729                              <1> ;        |    reserved byte    |     open count      |
  3730                              <1> ;        |-------------------------------------------| 
  3731                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3732                              <1> ;        |-------------------------------------------|
  3733                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3734                              <1> ;        |-------------------------------------------|
  3735                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3736                              <1> ;        |-------------------------------------------|
  3737                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3738                              <1> ;        |-------------------------------------------|
  3739                              <1> ;  2     |                                           |
  3740                              <1> ;        |-------------------------------------------| 
  3741                              <1> ;        |                                           |
  3742                              <1> ;        |-------------------------------------------|
  3743                              <1> ;        |                                           |
  3744                              <1> ;        |-------------------------------------------|
  3745                              <1> ;        |                                           |
  3746                              <1> ;        |-------------------------------------------| 
  3747                              <1> ;        |                                           | 
  3748                              <1> 
  3749                              <1> 	;
  3750                              <1> 	; 'fsp' table (10 bytes/entry)
  3751                              <1> 	; bit 15				   bit 0
  3752                              <1> 	; ---|-------------------------------------------
  3753                              <1> 	; r/w|		i-number of open file
  3754                              <1> 	; ---|-------------------------------------------
  3755                              <1> 	;		   device number
  3756                              <1> 	; -----------------------------------------------
  3757                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3758                              <1> 	; -----------------------------------------------
  3759                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3760                              <1> 	; ----------------------|------------------------
  3761                              <1> 	;  flag that says file 	| number of processes
  3762                              <1> 	;   has been deleted	| that have file open 
  3763                              <1> 	; ----------------------|------------------------
  3764                              <1> 	;
  3765                              <1> 
  3766                              <1> 	; 12/03/2022
  3767                              <1> 	; 11/02/2022
  3768                              <1> 	; 01/01/2022
  3769                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3770                              <1> syscreat: ; < create file >
  3771                              <1> 	; 12/03/2022
  3772                              <1> 	; 11/02/2022
  3773                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3774                              <1> 	; 04/04/2021
  3775                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3776                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3777                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3778                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3779                              <1> 	;
  3780                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3781                              <1> 	; u.namep points to name of the file and mode is put
  3782                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3783                              <1> 	; If the file aready exists, it's mode and owner remain 
  3784                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3785                              <1> 	; did not exist, an i-node is created with the new mode via
  3786                              <1> 	; 'maknod' whether or not the file already existed, it is
  3787                              <1> 	; open for writing. The fsp table is then searched for a free
  3788                              <1> 	; entry. When a free entry is found, proper data is placed
  3789                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3790                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3791                              <1> 	; is put in the user's r0. 			
  3792                              <1> 	;
  3793                              <1> 	; Calling sequence:
  3794                              <1> 	;	syscreate; name; mode
  3795                              <1> 	; Arguments:
  3796                              <1> 	;	name - name of the file to be created
  3797                              <1> 	;	mode - mode of the file to be created
  3798                              <1> 	; Inputs: (arguments)
  3799                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3800                              <1> 	;		   (the file descriptor of new file)
  3801                              <1> 	; ...............................................................
  3802                              <1> 	;				
  3803                              <1> 	; Retro UNIX 8086 v1 modification: 
  3804                              <1> 	;       'syscreate' system call has two arguments; so,
  3805                              <1> 	;	* 1st argument, name is pointed to by BX register
  3806                              <1> 	;	* 2nd argument, mode is in CX register
  3807                              <1> 	;
  3808                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3809                              <1> 	;	to the user with the file descriptor/number 
  3810                              <1> 	;	(index to u.fp list).
  3811                              <1> 	;
  3812                              <1> 	;call	arg2
  3813                              <1> 	; * name - 'u.namep' points to address of file/path name
  3814                              <1> 	;          in the user's program segment ('u.segmnt')
  3815                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3816                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3817                              <1> 	;          which is on top of stack.
  3818                              <1> 	;
  3819                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3820                              <1> 			    ; / on stack
  3821 00003FAC 891D[C8750000]      <1> 	mov	[u.namep], ebx ; file name address
  3822                              <1> 	;push	cx ; mode
  3823                              <1> 	; 04/12/2021
  3824 00003FB2 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3825 00003FB3 E8A00A0000          <1> 	call 	namei        	
  3826                              <1> 		; jsr r0,namei / get the i-number
  3827                              <1>         ;and	ax, ax
  3828                              <1> 	;jz	short syscreat_1	       	
  3829 00003FB8 7216                <1> 	jc	short syscreat_1
  3830                              <1> 		; br 2f / if file doesn't exist 2f
  3831                              <1> 	; 27/12/2015
  3832                              <1> 	;cmp	ax, 41 ; device inode ?
  3833                              <1>         ;jb	syscreat_0 ; yes
  3834                              <1> 	;
  3835                              <1> 	;neg 	ax
  3836                              <1>         ;	; neg r1 / if file already exists make i-number 
  3837                              <1> 		       ; / negative (open for writing)
  3838                              <1> 	; 11/02/2022
  3839                              <1> 	; Truncate existing file
  3840                              <1> ;syscreate_2:
  3841                              <1> 	;; 27/03/2021
  3842                              <1> 	;;xor	edx, edx ; 0
  3843                              <1> 	;;inc	dl ; DL = 1 ; create/truncate (open for write)
  3844                              <1> 	;mov	dl, 1
  3845                              <1> 	; 11/02/2022
  3846 00003FBA B202                <1> 	mov	dl, 2 ; create file (call from syscreat)
  3847 00003FBC E8B41E0000          <1> 	call	iopen
  3848                              <1>          	; jsr r0,iopen
  3849                              <1> 	; 11/02/2022
  3850                              <1> 	; cpu will return here if inode in eax is regular file inode
  3851                              <1> 	; (if it is device or dir inode, cpu will jumpt to 'error')
  3852                              <1> 	;
  3853                              <1> 	; 12/03/2022
  3854 00003FC1 50                  <1> 	push	eax ; * ; save inode number
  3855                              <1> 	; 
  3856                              <1> 	; truncate file to zero length
  3857                              <1> 	;call	itrunc
  3858                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3859                              <1> 	; 11/02/2022
  3860                              <1> 	; (iget and regular file check -in 'itrunc'- is not needed) 
  3861 00003FC2 E846170000          <1> 	call	itrunc_1
  3862                              <1> 	; 12/03/2022
  3863 00003FC7 58                  <1> 	pop	eax ; * ; restore inode number in eax
  3864                              <1> 	;
  3865                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3866                              <1> 	; 04/12/2021
  3867 00003FC8 59                  <1> 	pop	ecx
  3868                              <1> syscreat_2:
  3869 00003FC9 B201                <1> 	mov	dl, 1 ; open for writing
  3870 00003FCB E95BFFFFFF          <1>         jmp     sysopen_1
  3871                              <1>         	; br op0
  3872                              <1> syscreat_1: ; 2: / file doesn't exist
  3873                              <1> 	;pop	ax
  3874                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3875                              <1> 	; 27/03/2021
  3876 00003FD0 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3877                              <1> 	;xor	ah, ah	
  3878                              <1>         ;	; bic $!377,r1 / clear upper byte
  3879                              <1> 	; 27/03/2021
  3880                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  3881                              <1> 	; clear bits 15,14,13,12,9 of mode (input from user)
  3882 00003FD1 80E40D              <1> 	and	ah, 0Dh ; ISUID (800h) & ISGID (400h) & IREAD (100h)
  3883                              <1> 	; 11/02/2022
  3884 00003FD4 80CC80              <1> 	or	ah, 80h	; IFREG (8000h) ; Regular file
  3885 00003FD7 E8640D0000          <1> 	call 	maknod
  3886                              <1>         	; jsr r0,maknod / make an i-node for this file
  3887                              <1> 	;sub	eax, eax ; 04/12/2021
  3888 00003FDC 66A1[E4750000]      <1> 	mov	ax, [u.dirbuf]
  3889                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3890                              <1> 			        ; / for this new file in r1
  3891                              <1> 	; 04/04/2021
  3892                              <1> 	;mov	dl, 1 ; open for writing
  3893                              <1>         ;
  3894                              <1> 	;jmp	sysopen_1
  3895                              <1>         ;	; br op0 / open the file
  3896                              <1> 	; 04/04/2021
  3897 00003FE2 EBE5                <1> 	jmp	short syscreat_2
  3898                              <1> 
  3899                              <1> 	; 11/02/2022
  3900                              <1> 	; 04/12/2021
  3901                              <1> dir_access_err:	; 13/03/2022
  3902                              <1> ;	; 14/05/2015
  3903                              <1> ;	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3904                              <1> ;f_create_error:
  3905                              <1> 	; 27/03/2021
  3906 00003FE4 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; permission denied !	
  3906 00003FEC 0000                <1>
  3907 00003FEE E955FBFFFF          <1> 	jmp	error
  3908                              <1> 
  3909                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3910                              <1> sysmkdir: ; < make directory >
  3911                              <1> 	; 13/03/2022
  3912                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3913                              <1> 	; 02/04/2021
  3914                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3915                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3916                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3917                              <1> 	;
  3918                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3919                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3920                              <1> 	; The special entries '.' and '..' are not present.
  3921                              <1> 	; Errors are indicated if the directory already exists or		
  3922                              <1> 	; user is not the super user. 
  3923                              <1> 	;
  3924                              <1> 	; Calling sequence:
  3925                              <1> 	;	sysmkdir; name; mode
  3926                              <1> 	; Arguments:
  3927                              <1> 	;	name - points to the name of the directory
  3928                              <1> 	;	mode - mode of the directory
  3929                              <1> 	; Inputs: (arguments)
  3930                              <1> 	; Outputs: -
  3931                              <1> 	;    (sets 'directory' flag to 1; 
  3932                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3933                              <1> 	; ...............................................................
  3934                              <1> 	;				
  3935                              <1> 	; Retro UNIX 8086 v1 modification: 
  3936                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3937                              <1> 	;	* 1st argument, name is pointed to by BX register
  3938                              <1> 	;	* 2nd argument, mode is in CX register
  3939                              <1> 	;
  3940                              <1> 		
  3941                              <1> ; / make a directory
  3942                              <1> 
  3943                              <1> 	;call	arg2
  3944                              <1> 	; * name - 'u.namep' points to address of file/path name
  3945                              <1> 	;          in the user's program segment ('u.segmnt')
  3946                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3947                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3948                              <1> 	;          which is on top of stack.
  3949                              <1> 
  3950                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3951                              <1> 			    ; / on stack
  3952 00003FF3 891D[C8750000]      <1> 	mov	[u.namep], ebx
  3953                              <1> 	;push	cx ; mode
  3954                              <1> 	; 27/03/2021
  3955 00003FF9 51                  <1> 	push	ecx ; cx = mode
  3956 00003FFA E8590A0000          <1> 	call	namei
  3957                              <1>         	; jsr r0,namei / get the i-number
  3958                              <1>         	;     br .+4 / if file not found branch around error
  3959                              <1>         ;xor 	ax, ax
  3960                              <1> 	;jnz	error
  3961 00003FFF 7334                <1> 	jnc	short dir_exists ; 14/05/2015
  3962                              <1> 	;jnc	error	
  3963                              <1> 		; br error2 / directory already exists (error)
  3964                              <1> 
  3965                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  3966                              <1>         ;	;tstb u.uid / is user the super user
  3967                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3968                              <1> 	;;jna	error
  3969                              <1>         ;	;bne error2 / no, not allowed
  3970                              <1> 	;pop	ax
  3971                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3972                              <1> 	;and	ax, 0FFCFh ; 1111111111001111b
  3973                              <1>         ;	;bic $!317,r1 / all but su and ex
  3974                              <1> 	;;or	ax, 4000h ; 1011111111111111b
  3975                              <1> 	;or	ah, 40h ; Set bit 14 to 1
  3976                              <1>         ; 	;bis $40000,r1 / directory flag
  3977                              <1> 
  3978                              <1> 	; 02/04/2021
  3979                              <1> 	;cmp	word [u.uid], 0
  3980                              <1> 	;;ja	error
  3981                              <1> 	;ja	short dir_access_err
  3982                              <1> 
  3983                              <1> 	; 13/03/2022
  3984                              <1> 	; NOTE:
  3985                              <1> 	; Unix v5-v7 kernels do not allow (ordinary) users
  3986                              <1> 	; (except root/superuser) --if [u.uid] > 0--
  3987                              <1> 	; to make a sub directory. (ref: sys2.c, 'mknod')
  3988                              <1> 	;
  3989                              <1> 	; But, Retro UNIX 386 v1.2 will allow the owner of
  3990                              <1> 	; the parent directory to make a sub directory, here.
  3991                              <1> 
  3992                              <1> 	; 13/03/2022
  3993 00004001 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0
  3994 00004009 7618                <1> 	jna	short sysmkdir1 ; root (superuser)
  3995                              <1> 
  3996                              <1> 	; Here..
  3997                              <1> 	; (current) inode buffer contains inode structure
  3998                              <1> 	; of the parent directory (at the return of 'namei').
  3999                              <1> 
  4000 0000400B 66A1[5C710000]      <1> 	mov	ax, [i.uid] ; owner ID of the parent dir
  4001 00004011 663B05[FE750000]    <1> 	cmp	ax, [u.uid] ; user ID of current user/process
  4002 00004018 75CA                <1> 	jne	short dir_access_err
  4003                              <1> 	; 13/03/2022
  4004                              <1> 	; additional checking (may or may not be necessary!?)
  4005 0000401A 663B05[00760000]    <1> 	cmp	ax, [u.ruid] 
  4006                              <1> 			; real (login) user ID must be same
  4007 00004021 75C1                <1> 	jne	short dir_access_err
  4008                              <1> 
  4009                              <1> 	; 02/04/2021
  4010                              <1> 	; ('mkdir' procedure will be called from 'maknod'
  4011                              <1> 	; and then 'mkdir' will check write access permission) 
  4012                              <1> 	; ((so, 'access_w' call is not needed here.))
  4013                              <1> 
  4014                              <1> 	;; 02/04/2021
  4015                              <1> 	;; ('make directory' user permission check)
  4016                              <1> 	;; ((current directory's write permission flags
  4017                              <1> 	;;  will be checked against user's 'uid' & gid'))
  4018                              <1> 	;mov	dx, 80h ; IWRITE
  4019                              <1> 	;call	access_w  ; (in 'access', 'u5.s')
  4020                              <1> 	;; (If cpu will return here, the user has write permission)
  4021                              <1> 
  4022                              <1> sysmkdir1:
  4023                              <1> 	; 27/03/2021
  4024 00004023 58                  <1> 	pop	eax  ; ax = mode
  4025                              <1> 	; [ii] = current directory's inode number
  4026                              <1> 
  4027                              <1> 	; 27/03/2021
  4028                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  4029                              <1> 	; clear bits 13,12,11,10,9,6,3,0 of mode (input from user)
  4030                              <1> 	;and	ax, 0C1B6h ; bits 15,14,8,7,5,4,2,1
  4031 00004024 6625B601            <1> 	and	ax, 01B6h
  4032 00004028 80CCC0              <1> 	or	ah, 0C0h ; IFREG (8000h) + IFDIR (4000h) 
  4033                              <1> 			 ; Directory
  4034 0000402B E8100D0000          <1> 	call	maknod
  4035                              <1>         	;jsr r0,maknod / make the i-node for the directory
  4036 00004030 E933FBFFFF          <1> 	jmp	sysret
  4037                              <1>         	;br sysret2 /
  4038                              <1> dir_exists:
  4039                              <1> 	; 27/03/2021
  4040                              <1> 	; (same error number for files and directories)
  4041                              <1> 	; Error Number: 14 (ERR_DIR_EXISTS)
  4042 00004035 C705[20760000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS
  4042 0000403D 0000                <1>
  4043                              <1> 				; 'file already exists !' error
  4044                              <1> 	; 04/12/2021
  4045 0000403F E904FBFFFF          <1> 	jmp	error
  4046                              <1> ;dir_access_err:
  4047                              <1> ;	; 14/05/2015
  4048                              <1> ;	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  4049                              <1> ;	jmp	error
  4050                              <1> 
  4051                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4052                              <1> sysclose: ;<close file>
  4053                              <1> 	; 02/03/2022
  4054                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4055                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4056                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  4057                              <1> 	;
  4058                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  4059                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  4060                              <1> 	; is put in r1 and 'fclose' is called.
  4061                              <1> 	;
  4062                              <1> 	; Calling sequence:
  4063                              <1> 	;	sysclose
  4064                              <1> 	; Arguments:
  4065                              <1> 	;	-  
  4066                              <1> 	; Inputs: *u.r0 - file descriptor
  4067                              <1> 	; Outputs: -
  4068                              <1> 	; ...............................................................
  4069                              <1> 	;				
  4070                              <1> 	; Retro UNIX 8086 v1 modification:
  4071                              <1> 	;	 The user/application program puts file descriptor
  4072                              <1> 	;        in BX register as 'sysclose' system call argument.
  4073                              <1> 	; 	 (argument transfer method 1)
  4074                              <1> 
  4075                              <1> 	; / close the file
  4076                              <1> 	
  4077                              <1> 	;mov 	eax, ebx
  4078                              <1> 	; 04/12/2021
  4079                              <1> 	; ebx = file descriptor/number
  4080                              <1> 	;call 	fclose
  4081                              <1> 	; 02/03/2022
  4082 00004044 E893090000          <1> 	call	_fclose
  4083                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  4084                              <1> 		; jsr r0,fclose / close the file
  4085                              <1>                	; br error2 / unknown file descriptor
  4086                              <1> 		; br sysret2
  4087                              <1> 	;; 14/05/2015
  4088                              <1> 	;jnc	sysret
  4089                              <1> 	; 04/12/2021
  4090 00004049 7205                <1> 	jc	short sysclose_err
  4091 0000404B E918FBFFFF          <1> 	jmp	sysret
  4092                              <1> sysclose_err:
  4093 00004050 C705[20760000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  4093 00004058 0000                <1>
  4094 0000405A E9E9FAFFFF          <1> 	jmp	error
  4095                              <1> 
  4096                              <1> 	; 23/02/2022
  4097                              <1> 	; 19/12/2021
  4098                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4099                              <1> sysemt:
  4100                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4101                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4102                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  4103                              <1> 	;
  4104                              <1> 	; Retro UNIX 8086 v1 modification: 
  4105                              <1> 	;	'Enable Multi Tasking' system call instead 
  4106                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  4107                              <1> 	;
  4108                              <1> 	; Retro UNIX 8086 v1 feature only!
  4109                              <1> 	;	Using purpose: Kernel will start without time-out
  4110                              <1> 	;	(internal clock/timer) functionality.
  4111                              <1> 	;	Then etc/init will enable clock/timer for
  4112                              <1> 	;	multi tasking. (Then it will not be disabled again
  4113                              <1> 	;	except hardware reset/restart.)
  4114                              <1> 	;
  4115                              <1> 	
  4116                              <1> 	;cmp	byte [u.uid], 0 ; root ?
  4117                              <1> 	;;ja	error
  4118                              <1> 	;ja	badsys ; 14/05/2015
  4119                              <1> 	; 04/12/2021
  4120 0000405F 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0 ; root ?
  4121 00004067 7605                <1> 	jna	short emt_0 
  4122 00004069 E98CFBFFFF          <1> 	jmp	badsys
  4123                              <1> emt_0:
  4124 0000406E FA                  <1> 	cli	; 23/02/2022
  4125 0000406F 21DB                <1> 	and	ebx, ebx
  4126 00004071 7429                <1> 	jz	short emt_2
  4127                              <1> 	; Enable multi tasking -time sharing-
  4128 00004073 B8[B5500000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  4129                              <1> 	; 23/02/2022
  4130 00004078 BA[4A0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  4131                              <1> emt_1:
  4132 0000407D A3[0F070000]        <1> 	mov	[x_timer], eax
  4133                              <1> 	; 23/02/2022 (Temporary)
  4134 00004082 8915[13070000]      <1> 	mov	[x_rtci], edx
  4135 00004088 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  4136 0000408A E855020000          <1> 	call	wttyc  ; clear video page
  4137 0000408F B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  4138 00004091 E84E020000          <1> 	call	wttyc  ; clear video page
  4139                              <1> 	;
  4140 00004096 FB                  <1> 	sti	; 23/02/2022
  4141 00004097 E9CCFAFFFF          <1> 	jmp	sysret
  4142                              <1> emt_2:
  4143                              <1> 	; Disable multi tasking -time sharing-
  4144 0000409C B8[1B070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  4145                              <1> 	; 23/02/2022
  4146 000040A1 BA[510A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  4147                              <1> 	;
  4148 000040A6 EBD5                <1> 	jmp	short emt_1
  4149                              <1> 
  4150                              <1> 	; Original UNIX v1 'sysemt' routine
  4151                              <1> ;sysemt:
  4152                              <1>         ;
  4153                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  4154                              <1> 			 ; / in loc 30
  4155                              <1>         ;cmp    30,$core / was the argument a lower address 
  4156                              <1> 			; / than core
  4157                              <1>         ;blo    1f / yes, rtssym
  4158                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  4159                              <1> 			; / and less than "ecore"
  4160                              <1>         ;blo    2f / yes, sysret2
  4161                              <1> ;1:
  4162                              <1>         ;mov    $rtssym,30
  4163                              <1> ;2:
  4164                              <1>         ;br     sysret2
  4165                              <1> 
  4166                              <1> sysilgins:
  4167                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4168                              <1> 	; 03/06/2013
  4169                              <1> 	; Retro UNIX 8086 v1 modification: 
  4170                              <1> 	;	not a valid system call ! (not in use)
  4171                              <1> 	;
  4172 000040A8 E94DFBFFFF          <1> 	jmp	badsys
  4173                              <1> 	;jmp	error
  4174                              <1> 	;;jmp 	sysret
  4175                              <1> 
  4176                              <1> 	; Original UNIX v1 'sysemt' routine
  4177                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  4178                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  4179                              <1> 			  ;/ put it in loc 8.,
  4180                              <1>         ;cmp    10,$core / making it the illegal instruction 
  4181                              <1> 		       ; / trap address
  4182                              <1>         ;blo    1f / is the address a user core address?  
  4183                              <1> 		; / yes, go to 2f
  4184                              <1>         ;cmp    10,$ecore
  4185                              <1>         ;blo    2f
  4186                              <1> ;1:
  4187                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  4188                              <1> 		    ; / instruction trap address for the system
  4189                              <1> ;2:
  4190                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  4191                              <1> 
  4192                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4193                              <1> sysmdate: ; < change the modification time of a file >
  4194                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  4195                              <1> 	;	(ECX input)
  4196                              <1> 	; 24/12/2021
  4197                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4198                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  4199                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4200                              <1> 	;
  4201                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  4202                              <1> 	; file into core. The user is checked if he is the owner 
  4203                              <1> 	; or super user. If he is neither an error occurs.
  4204                              <1> 	; 'setimod' is then called to set the i-node modification
  4205                              <1> 	; byte and the modification time, but the modification time
  4206                              <1> 	; is overwritten by whatever get put on the stack during
  4207                              <1> 	; a 'systime' system call. This calls are restricted to
  4208                              <1> 	; the super user.		
  4209                              <1> 	;
  4210                              <1> 	; Calling sequence:
  4211                              <1> 	;	sysmdate; name
  4212                              <1> 	; Arguments:
  4213                              <1> 	;	name - points to the name of file
  4214                              <1> 	; Inputs: (arguments)
  4215                              <1> 	; Outputs: -
  4216                              <1> 	; ...............................................................
  4217                              <1> 	;				
  4218                              <1> 	; Retro UNIX 8086 v1 modification: 
  4219                              <1> 	;	 The user/application program puts address 
  4220                              <1> 	;	 of the file name in BX register 
  4221                              <1> 	;	 as 'sysmdate' system call argument.
  4222                              <1> 	;
  4223                              <1> ; / change the modification time of a file
  4224                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  4225 000040AD 891D[C8750000]      <1>         mov	[u.namep], ebx
  4226                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  4227 000040B3 890D[E0700000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  4228 000040B9 E89A090000          <1> 	call	namei
  4229                              <1> 		; jsr r0,namei / get its i-number
  4230                              <1> 	;;jc	error       
  4231                              <1> 	;	; br error2 / no, such file
  4232                              <1> 	;jc	fnotfound ; file not found !
  4233                              <1> 	; 24/12/2021
  4234 000040BE 7305                <1> 	jnc	short mdate_0
  4235 000040C0 E988FEFFFF          <1> 	jmp	fnotfound
  4236                              <1> mdate_0: 
  4237 000040C5 E84B140000          <1> 	call	iget
  4238                              <1> 		; jsr r0,iget / get i-node into core
  4239                              <1> 	;mov	al, [u.uid]
  4240                              <1> 	;cmp	al, [i.uid]
  4241                              <1>         ;	; cmpb u.uid,i.uid / is user same as owner
  4242                              <1> 	;je	short mdate_1
  4243                              <1>         ;	; beq 1f / yes
  4244                              <1> 	;and	al, al
  4245                              <1> 	;	; tstb u.uid / no, is user the super user
  4246                              <1> 	;;jnz	error
  4247                              <1> 	;	; bne error2 / no, error
  4248                              <1> 	;jz	short mdate_1
  4249                              <1> 	; 04/12/2021
  4250 000040CA 66A1[FE750000]      <1> 	mov	ax, [u.uid]
  4251 000040D0 663B05[5C710000]    <1> 	cmp	ax, [i.uid]
  4252 000040D7 7414                <1> 	je	short mdate_1	
  4253 000040D9 6621C0              <1> 	and	ax, ax
  4254 000040DC 740F                <1> 	jz	short mdate_1
  4255                              <1> 
  4256 000040DE C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4256 000040E6 0000                <1>
  4257                              <1> sysstty_err:	; 06/02/2022
  4258 000040E8 E95BFAFFFF          <1> 	jmp	error
  4259                              <1> mdate_1: ;1:
  4260 000040ED E8B4150000          <1> 	call	setimod
  4261                              <1>         	; jsr r0,setimod / fill in modification data,
  4262                              <1> 		               ; / time etc.
  4263 000040F2 BE[E0700000]        <1> 	mov	esi, p_time
  4264 000040F7 BF[90710000]        <1> 	mov	edi, i.mtim
  4265 000040FC A5                  <1> 	movsd
  4266                              <1> 		; mov 4(sp),i.mtim / move present time to
  4267                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4268 000040FD E966FAFFFF          <1>         jmp	sysret
  4269                              <1> 		; br sysret2
  4270                              <1> 
  4271                              <1> 	; 06/02/2022
  4272                              <1> sysstty_err_s:
  4273 00004102 880D[AC750000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4274 00004108 EBDE                <1> 	jmp	short sysstty_err
  4275                              <1> 
  4276                              <1> sysstty: ; < set tty status and mode >
  4277                              <1> 	; 22/02/2022
  4278                              <1> 	; 21/02/2022
  4279                              <1> 	; 06/02/2022 (Retro UNIX 286 v1.2)
  4280                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4281                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4282                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4283                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4284                              <1> 	;	    ((32 bit reg push/pop))
  4285                              <1> 	; 17/11/2015
  4286                              <1> 	; 12/11/2015
  4287                              <1> 	; 29/10/2015
  4288                              <1> 	; 17/10/2015
  4289                              <1> 	; 13/10/2015
  4290                              <1> 	; 29/06/2015
  4291                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4292                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4293                              <1> 	;
  4294                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4295                              <1> 	; whose file descriptor is in (u.r0).
  4296                              <1> 	;
  4297                              <1> 	; Calling sequence:
  4298                              <1> 	;	sysstty; arg
  4299                              <1> 	; Arguments:
  4300                              <1> 	;	arg - address of 3 consequitive words that contain
  4301                              <1> 	;	      the source of status data	
  4302                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4303                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4304                              <1> 	; ...............................................................
  4305                              <1> 	;	
  4306                              <1> 	; Retro UNIX 8086 v1 modification: 
  4307                              <1> 	;	'sysstty' system call will set the tty
  4308                              <1> 	;	(clear keyboard buffer and set cursor position)
  4309                              <1> 	;	 in following manner:
  4310                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4311                              <1> 	;
  4312                              <1> 	; Inputs:
  4313                              <1> 	;	BX = 0 --> means
  4314                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4315                              <1> 	;	      set cursor position for console tty, only 
  4316                              <1> 	;	      CH will be ignored (char. will not be written)
  4317                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4318                              <1> 	;	      set console tty for (current) process
  4319                              <1> 	;	      CL = tty number (0 to 9)
  4320                              <1> 	;	      (If CH = 0, character will not be written)
  4321                              <1> 	;          If CH > 0 (CL < FFh)	
  4322                              <1> 	;             CL = tty number (0 to 9)
  4323                              <1> 	;	      CH = character will be written
  4324                              <1> 	;	        at requested cursor position (in DX)
  4325                              <1> 	;	   DX = cursor position for tty number 0 to 7.
  4326                              <1>   	;		(only tty number 0 to 7) 
  4327                              <1> 	;          DL = communication parameters (for serial ports)
  4328                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4329                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4330                              <1> 	;			or set cursor position	
  4331                              <1> 	;	   DH = 0FFh -> DL is not valid
  4332                              <1> 	;		do not set serial port parameters 
  4333                              <1> 	;		or do not set cursor position
  4334                              <1> 	;
  4335                              <1> 	;	BX > 0 --> points to name of tty
  4336                              <1> 	;    	   CH > 0 -->
  4337                              <1> 	;		CH = character will be written in current 
  4338                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4339                              <1> 	;	     	or character will be sent to serial port
  4340                              <1> 	;	     	(for tty number 8 or 9)
  4341                              <1> 	;		CL = color of the character if tty number < 8.
  4342                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4343                              <1> 	;		set mode (tty 8 to 9) or 
  4344                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4345                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4346                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4347                              <1> 	;		(DL is not valid)
  4348                              <1> 	;	   DL = communication parameters 
  4349                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4350                              <1> 	;
  4351                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4352                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4353                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4354                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4355                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4356                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4357                              <1> 	;
  4358                              <1> 	; Outputs:
  4359                              <1> 	;	cf = 0 -> OK
  4360                              <1> 	;	     AL = tty number (0 to 9)
  4361                              <1> 	;	     AH = line status if tty number is 8 or 9
  4362                              <1> 	;	     AH = process number (of the caller)
  4363                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4364                              <1> 	;	     AH = FFh if the tty is locked 
  4365                              <1> 	;		  (owned by another process)
  4366                              <1> 	;	        = process number (of the caller) 
  4367                              <1> 	;		  (if < FFh and tty number < 8)
  4368                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4369                              <1> 	;	     AH = line status if tty number is 8 or 9
  4370                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4371                              <1> 	;	
  4372                              <1> 
  4373                              <1> 	; 27/06/2015 (32 bit modifications)
  4374                              <1> 	; 14/01/2014
  4375 0000410A 31C0                <1> 	xor 	eax, eax
  4376 0000410C 6648                <1> 	dec	ax ; 17/10/2015
  4377 0000410E A3[AC750000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4378                              <1> 	;;;
  4379                              <1> 	; 01/02/2022
  4380 00004113 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4381 00004115 39C2                <1> 	cmp	edx, eax
  4382                              <1> 	;cmp	dx, ax ; 0FFFFh
  4383 00004117 7521                <1> 	jne	short sysstty_18
  4384                              <1> 	; clear video page
  4385                              <1> 	; (CH must be 0)
  4386 00004119 08ED                <1> 	or	ch, ch
  4387 0000411B 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4388 0000411D 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4389 00004120 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4390 00004122 20C9                <1> 	and	cl, cl
  4391 00004124 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4392 00004126 0FB635[FD750000]    <1> 	movzx	esi, byte [u.uno]
  4393 0000412D 8A8E[D7710000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4394 00004133 80F907              <1> 	cmp	cl, 7
  4395 00004136 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4396                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4397 00004138 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4398                              <1> sysstty_18:
  4399 0000413A FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4400                              <1> 	; cl = video page (tty) number
  4401                              <1> 	;;;
  4402 0000413C 21DB                <1> 	and	ebx, ebx
  4403                              <1> 	;jnz	sysstty_6
  4404                              <1> 	; 01/02/2022
  4405 0000413E 7405                <1> 	jz	short sysstty_19
  4406 00004140 E9C2000000          <1> 	jmp	sysstty_6
  4407                              <1> sysstty_19:
  4408                              <1> 	; set console tty
  4409                              <1> 	; 29/10/2015
  4410                              <1> 	; 17/01/2014 
  4411 00004145 80F909              <1> 	cmp	cl, 9
  4412 00004148 7613                <1> 	jna	short sysstty_0
  4413                              <1> 	; 17/11/2015
  4414 0000414A 80F9FF              <1> 	cmp	cl, 0FFh
  4415 0000414D 7202                <1> 	jb	short sysstty_13
  4416 0000414F 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4417                              <1> sysstty_13:
  4418 00004151 8A1D[FD750000]      <1> 	mov	bl, [u.uno] ; process number
  4419 00004157 8A8B[D7710000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4420                              <1> sysstty_0:
  4421                              <1> 	; 29/06/2015
  4422 0000415D 52                  <1> 	push	edx ; 24/12/2021
  4423 0000415E 51                  <1> 	push	ecx
  4424 0000415F 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4425 00004161 88C8                <1> 	mov	al, cl
  4426 00004163 A2[AC750000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4427 00004168 E8D51D0000          <1> 	call	ottyp
  4428 0000416D 59                  <1> 	pop	ecx
  4429 0000416E 5A                  <1> 	pop	edx
  4430                              <1> 	;
  4431 0000416F 7220                <1> 	jc	short sysstty_pd_err
  4432                              <1> 	;
  4433                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4434                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4435                              <1> 	;
  4436 00004171 80F908              <1> 	cmp	cl, 8
  4437 00004174 720C                <1> 	jb	short sysstty_2
  4438                              <1> 	;
  4439 00004176 80FEFF              <1> 	cmp	dh, 0FFh
  4440 00004179 7407                <1> 	je	short sysstty_2
  4441                              <1> 
  4442                              <1> ; 01/02/2022
  4443                              <1> ;	; 29/10/2015
  4444                              <1> ;	mov	ah, dl ; communication parameters
  4445                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4446                              <1> ;		;			 THRE int + RDA int 
  4447                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4448                              <1> ;		;			 THRE int + RDA int 
  4449                              <1> ;	sub	al, al ; 0
  4450                              <1> ;	; 12/07/2014
  4451                              <1> ;	cmp	cl, 9
  4452                              <1> ;	jb	short sysstty_1
  4453                              <1> ;	inc	al
  4454                              <1> ;sysstty_1:
  4455                              <1> ;	; 01/02/2022
  4456                              <1> ;	push	ecx
  4457                              <1> ;	; 29/06/2015	
  4458                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4459                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4460                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4461                              <1> ;	; 01/02/2022
  4462                              <1> ;	pop	ecx	
  4463                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4464                              <1> 
  4465                              <1> 	; 01/02/2022
  4466 0000417B E831010000          <1> 	call	sysstty_scp
  4467 00004180 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4468                              <1> 
  4469                              <1> sysstty_2:
  4470                              <1> 	; 17/01/2014
  4471 00004182 20ED                <1> 	and	ch, ch 	; set cursor position 
  4472                              <1> 			; or comm. parameters ONLY
  4473 00004184 7527                <1> 	jnz	short sysstty_3
  4474                              <1> 	; 01/02/2022
  4475 00004186 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4476 0000418A 7214                <1> 	jb	short sysstty_20
  4477                              <1> 	; clear screen (video page)
  4478 0000418C E93C010000          <1> 	jmp	sysstty_14
  4479                              <1> 
  4480                              <1> sysstty_pd_err: ; 29/06/2015
  4481                              <1> 	; 'permission denied !' error
  4482 00004191 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4482 00004199 0000                <1>
  4483 0000419B E9A8F9FFFF          <1> 	jmp	error
  4484                              <1> 
  4485                              <1> sysstty_20:
  4486 000041A0 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4487 000041A7 888B[D7710000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4488                              <1> sysstty_3:
  4489                              <1> 	; 16/01/2014
  4490 000041AD 88E8                <1> 	mov	al, ch ; character  ; 0 to FFh
  4491                              <1> 	; 17/11/2015
  4492 000041AF B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4493 000041B1 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4494                              <1>         ;jna	sysstty_9
  4495                              <1> 	; 24/12/2021
  4496 000041B3 7705                <1> 	ja	short sysstty_12
  4497 000041B5 E9C6000000          <1> 	jmp	sysstty_9
  4498                              <1> 
  4499                              <1> sysstty_12:
  4500                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4501                              <1> 	; (Set specified serial port as console tty port)
  4502                              <1> 	; CH = character to be written
  4503                              <1> 	; 15/04/2014
  4504                              <1> 	; CH = 0 --> initialization only
  4505                              <1> 	; AL = character
  4506                              <1> 	; 26/06/2014
  4507 000041BA 880D[E1750000]      <1> 	mov	[u.ttyn], cl
  4508                              <1> 	; 12/07/2014
  4509 000041C0 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4510                              <1> 	; 02/02/2022
  4511 000041C2 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4512 000041C4 740B                <1> 	jz	short sysstty_4 ; al = ch = 0
  4513 000041C6 FEC8                <1> 	dec	al  ; 1 -> 0	
  4514                              <1> 	;and	al, al
  4515 000041C8 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4516                              <1>  	; 04/07/2014
  4517 000041CA E8C6230000          <1> 	call 	sndc
  4518                              <1> 	; 12/07/2014
  4519 000041CF EB0C                <1> 	jmp	short sysstty_5
  4520                              <1> 
  4521                              <1> sysstty_4:
  4522                              <1> 	; 12/07/2014
  4523                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4524 000041D1 88E0                <1> 	mov	al, ah ; 29/06/2015
  4525 000041D3 2C08                <1> 	sub	al, 8
  4526                              <1> 	; 27/06/2015
  4527 000041D5 E89EF3FFFF          <1> 	call	sp_status ; get serial port status
  4528                              <1> 	; AL = Line status, AH = Modem status
  4529                              <1> 	; 12/11/2015
  4530 000041DA 3C80                <1> 	cmp	al, 80h
  4531 000041DC F5                  <1> 	cmc
  4532                              <1> sysstty_5:
  4533 000041DD 66A3[AD750000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4534                              <1> 		; EAX bits 16-23 = modem status	
  4535 000041E3 9C                  <1> 	pushf
  4536 000041E4 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4537 000041E6 A0[E1750000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4538 000041EB E8851E0000          <1> 	call	cttyp
  4539 000041F0 9D                  <1> 	popf
  4540                              <1> 	;jnc	sysret ; time out error 
  4541                              <1> 	; 01/02/2022
  4542 000041F1 7205                <1> 	jc	short sysstty_tmout_err
  4543 000041F3 E970F9FFFF          <1> 	jmp	sysret
  4544                              <1> 
  4545                              <1> 	; time out error 
  4546                              <1> sysstty_tmout_err:
  4547 000041F8 C705[20760000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4547 00004200 0000                <1>
  4548 00004202 E941F9FFFF          <1> 	jmp	error
  4549                              <1> 
  4550                              <1> sysstty_6:
  4551 00004207 52                  <1> 	push	edx ; 24/12/2021
  4552 00004208 51                  <1> 	push	ecx
  4553 00004209 891D[C8750000]      <1> 	mov	[u.namep], ebx
  4554 0000420F E844080000          <1> 	call	namei
  4555 00004214 59                  <1> 	pop	ecx
  4556 00004215 5A                  <1> 	pop	edx
  4557 00004216 7259                <1> 	jc	short sysstty_inv_dn
  4558                              <1> 	;
  4559                              <1> 	; 21/02/2022
  4560                              <1> 	;cmp	ax, 19  ; inode number of /dev/COM2
  4561                              <1> 	;ja	short sysstty_inv_dn ; 27/06/2015
  4562                              <1> 	;;
  4563                              <1> 	;cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4564                              <1> 	;	       ; /dev/COM1, /dev/COM2
  4565                              <1> 	;jb	short sysstty_7
  4566                              <1> 	;sub	al, 10
  4567                              <1> 	;jmp	short sysstty_8
  4568                              <1> 	;
  4569                              <1> 	; 21/02/2022
  4570                              <1> 	; (Retro UNIX 386 v2 file system inode numbers)
  4571 00004218 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  4572 0000421B 7754                <1> 	ja	short sysstty_inv_dn
  4573                              <1> 	;cmp	al, 8	; /dev/tty inode number is 8
  4574                              <1> 	;jb	short sysstty_inv_dn
  4575 0000421D 2C08                <1> 	sub	al, 8
  4576 0000421F 7250                <1> 	jb	short sysstty_inv_dn
  4577 00004221 7408                <1> 	jz	short sysstty_7 ; /dev/tty inode number is 8
  4578                              <1> 	; convert inode number to tty number (tty0 to tty9)
  4579 00004223 2C09                <1> 	sub	al, 9
  4580 00004225 724A                <1> 	jb	short sysstty_inv_dn
  4581                              <1> 	; al = 0 to 9
  4582 00004227 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4583 00004229 EB0D                <1> 	jmp	short sysstty_8 
  4584                              <1> sysstty_7:
  4585                              <1> 	; 21/02/2022
  4586                              <1> 	;cmp	al, 1 ; /dev/tty
  4587                              <1> 	;jne	short sysstty_inv_dn ; 27/06/2015
  4588 0000422B 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4589 00004232 8A83[D7710000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4590                              <1> sysstty_8:
  4591                              <1> 	; 22/02/2022
  4592                              <1> 	; (ebx < 256)	
  4593 00004238 A2[AC750000]        <1> 	mov	[u.r0], al
  4594 0000423D 52                  <1> 	push	edx ; 24/12/2021
  4595 0000423E 50                  <1> 	push	eax
  4596 0000423F 51                  <1> 	push	ecx	
  4597 00004240 E8FD1C0000          <1> 	call	ottyp
  4598 00004245 59                  <1> 	pop	ecx
  4599 00004246 58                  <1> 	pop	eax
  4600 00004247 5A                  <1> 	pop	edx
  4601                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4602                              <1> 	; 06/02/2022
  4603 00004248 7305                <1> 	jnc	short sysstty_21
  4604                              <1> 	; 'permission denied !'
  4605 0000424A E942FFFFFF          <1> 	jmp	sysstty_pd_err
  4606                              <1> sysstty_21:
  4607                              <1> 	; 29/10/2015
  4608 0000424F 86E9                <1> 	xchg 	ch, cl
  4609                              <1> 		; cl = character, ch = color code
  4610 00004251 86C1                <1> 	xchg	al, cl
  4611                              <1> 		; al = character, cl = tty number
  4612 00004253 80F907              <1> 	cmp	cl, 7
  4613                              <1> 	;ja	sysstty_12
  4614                              <1> 	; 06/02/2022
  4615 00004256 7628                <1> 	jna	short sysstty_16
  4616                              <1> ;;
  4617 00004258 80FEFF              <1> 	cmp	dh, 0FFh
  4618 0000425B 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4619                              <1> 
  4620                              <1> ; 01/02/2022
  4621                              <1> ;	; 29/10/2015
  4622                              <1> ;	mov	ah, dl ; communication parameters
  4623                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4624                              <1> ;		;			 THRE int + RDA int 
  4625                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4626                              <1> ;		;			 THRE int + RDA int 
  4627                              <1> ;	sub	al, al ; 0
  4628                              <1> ;	; 12/07/2014
  4629                              <1> ;	cmp	cl, 9
  4630                              <1> ;	jb	short sysstty_1
  4631                              <1> ;	inc	al
  4632                              <1> ;sysstty_1:
  4633                              <1> ;	; 01/02/2022
  4634                              <1> ;	push	ecx
  4635                              <1> ;	; 29/06/2015	
  4636                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4637                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4638                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4639                              <1> ;	; 01/02/2022
  4640                              <1> ;	pop	ecx	
  4641                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4642                              <1> 
  4643                              <1> 	; 02/02/2022
  4644 0000425D 88C5                <1> 	mov	ch, al ; save char
  4645                              <1> 	; 01/02/2022
  4646 0000425F E84D000000          <1> 	call	sysstty_scp
  4647 00004264 7292                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4648                              <1> 	; 02/02/2022
  4649 00004266 88E8                <1> 	mov	al, ch ; restore char
  4650                              <1> sysstty_22:
  4651                              <1> 	; 01/02/2022
  4652 00004268 08ED                <1> 	or	ch, ch
  4653 0000426A 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4654                              <1> 	; send char to (serial port) terminal
  4655                              <1> 	; al = character
  4656                              <1> 	; cl = tty number (8 or 9)
  4657 0000426C E949FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4658                              <1> 
  4659                              <1> sysstty_inv_dn: 
  4660                              <1> 	; 27/06/2015
  4661                              <1> 	; Invalid device name (not a tty) ! error
  4662                              <1> 	; (Device is not a tty or device name not found)
  4663 00004271 C705[20760000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4663 00004279 0000                <1>
  4664 0000427B E9C8F8FFFF          <1> 	jmp	error
  4665                              <1> 
  4666                              <1> sysstty_16:
  4667                              <1> 	; 22/02/2022
  4668                              <1> 	; 16/01/2014
  4669                              <1> 	;xor	bh, bh
  4670                              <1> sysstty_9: 	; tty 0 to tty 7
  4671                              <1> 	; al = character
  4672                              <1> 	; ch = color/attribute ; 01/02/2022
  4673                              <1> 	;
  4674                              <1>  	; 22/02/2022 (BugFix)
  4675                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4676 00004280 29DB                <1> 	sub	ebx, ebx ; *
  4677 00004282 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4678                              <1> 	;
  4679 00004284 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4680 00004287 7409                <1> 	je	short sysstty_10
  4681                              <1> 	; 24/12/2021
  4682 00004289 51                  <1> 	push	ecx
  4683 0000428A 50                  <1> 	push	eax
  4684                              <1> 	; 22/02/2022	
  4685                              <1> 	;;movzx	ebx, cl ; *
  4686                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4687 0000428B E83ED2FFFF          <1> 	call	set_cpos
  4688 00004290 58                  <1> 	pop	eax
  4689 00004291 59                  <1> 	pop	ecx
  4690                              <1> sysstty_10: 
  4691                              <1> 	; 22/02/2022
  4692                              <1> 	; bl = video page (tty) number 
  4693                              <1> 	;
  4694                              <1> 	; 29/10/2015
  4695 00004292 08C0                <1> 	or	al, al ; character
  4696 00004294 740D                <1> 	jz      short sysstty_11 ; al = 0
  4697                              <1> 	; 17/11/2015
  4698 00004296 3CFF                <1> 	cmp	al, 0FFh
  4699 00004298 7309                <1> 	jnb	short sysstty_11
  4700                              <1> 		; ch > 0 and ch < FFh
  4701                              <1> 	; write a character at current cursor position
  4702 0000429A 88EC                <1> 	mov	ah, ch ; color/attribute
  4703                              <1> 	; 12/07/2014
  4704 0000429C 51                  <1> 	push	ecx ; 24/12/2021
  4705 0000429D E818D3FFFF          <1> 	call	write_c_current
  4706 000042A2 59                  <1> 	pop	ecx
  4707                              <1> sysstty_11:
  4708                              <1> 	; 14/01/2014
  4709 000042A3 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4710                              <1> 	; 18/01/2014
  4711                              <1> 	;movzx	eax, cl ; 27/06/2015
  4712 000042A5 88C8                <1> 	mov	al, cl
  4713 000042A7 E8C91D0000          <1> 	call	cttyp
  4714 000042AC E9B7F8FFFF          <1> 	jmp	sysret
  4715                              <1> 
  4716                              <1> 	; 06/02/2022 (Retro UNIX 386 v1.2)
  4717                              <1> sysstty_scp:
  4718                              <1> 	; 02/02/2022
  4719                              <1> 	; set communication parameters (for COM1 or COM2)
  4720                              <1> 	; 01/02/2022
  4721                              <1> 	;
  4722                              <1> 	; 29/10/2015
  4723 000042B1 88D4                <1> 	mov	ah, dl ; communication parameters
  4724                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4725                              <1> 		;			 THRE int + RDA int 
  4726                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4727                              <1> 		;			 THRE int + RDA int 
  4728 000042B3 28C0                <1> 	sub	al, al ; 0
  4729                              <1> 	; 12/07/2014
  4730 000042B5 80F909              <1> 	cmp	cl, 9
  4731 000042B8 7202                <1> 	jb	short sysstty_1
  4732 000042BA FEC0                <1> 	inc	al
  4733                              <1> sysstty_1:
  4734                              <1> 	; 02/02/2022
  4735 000042BC 52                  <1> 	push	edx
  4736                              <1> 	; 01/02/2022
  4737 000042BD 51                  <1> 	push	ecx
  4738                              <1> 	; 29/06/2015	
  4739 000042BE E8BDF2FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4740 000042C3 66890D[AD750000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4741                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4742                              <1> 	; 01/02/2022
  4743 000042CA 59                  <1> 	pop	ecx	
  4744 000042CB 5A                  <1> 	pop	edx ; 02/02/2022
  4745                              <1> 	; 01/02/2022
  4746                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4747 000042CC C3                  <1> 	retn
  4748                              <1> 
  4749                              <1> 	; 06/02/2022 (Retro UNIX 386 v1.2)
  4750                              <1> sysstty_14:
  4751                              <1> 	; 23/02/2022
  4752                              <1> 	; 02/02/2022
  4753                              <1> 	; ch = 0
  4754                              <1> 	; cl = video page
  4755                              <1> 	;
  4756                              <1> 	; dx = 0FFFFh
  4757                              <1> 	; clear screen (video page)
  4758                              <1> 	;
  4759                              <1> 
  4760                              <1> 	; 02/02/2022
  4761                              <1> 	; clear screen
  4762                              <1> 	;
  4763                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4764                              <1> 
  4765                              <1> 	; 23/02/2022
  4766 000042CD 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4767                              <1> 
  4768                              <1> 	; clear video page
  4769 000042CF E810000000          <1> 	call	wttyc ; 23/02/2022
  4770                              <1> 
  4771                              <1> 	; 23/02/2022
  4772 000042D4 88D8                <1> 	mov	al, bl
  4773 000042D6 8A25[FD750000]      <1> 	mov	ah, [u.uno]
  4774 000042DC 66A3[AC750000]      <1> 	mov	[u.r0], ax
  4775 000042E2 EBBF                <1> 	jmp	short sysstty_11
  4776                              <1> 
  4777                              <1> wttyc:
  4778                              <1> 	; 23/02/2022
  4779                              <1> 	; (clear video page)
  4780                              <1> 	; INPUT:
  4781                              <1> 	;  bl = video page (0 to 7)
  4782                              <1> 	;
  4783                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4784                              <1> 
  4785                              <1> 	;xor	dx, dx ; column 0, row 0
  4786                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4787                              <1> 	;
  4788                              <1> ;	movzx	ebx, cl
  4789                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4790                              <1> 
  4791                              <1> ;	shl 	bl, 1 
  4792                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4793                              <1> ;		; AL = lock value (0 or process number)
  4794                              <1> ;	or	al, al
  4795                              <1> ;	jz	short @f
  4796                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4797                              <1> ;	jne	short sysstty_15
  4798                              <1> ;		; only the owner can clear its video page
  4799                              <1> ;	xor	al, al ; 0
  4800                              <1> ;@@:
  4801                              <1> ;	;mov	bl, cl		
  4802                              <1> ;	shr	bl, 1 
  4803                              <1> 
  4804 000042E4 30C0                <1> 	xor	al, al	; 0
  4805 000042E6 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4806                              <1> 
  4807                              <1> 	; scroll_up input:
  4808                              <1> 	;
  4809                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4810                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4811                              <1> 	; ah = attribute to be used on blanked line
  4812                              <1> 	; bl = video page number (0 to 7)
  4813                              <1> 
  4814 000042E8 E86BD2FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4815                              <1> 
  4816                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4817                              <1> 
  4818                              <1> 	; bl = video page number (0 to 7)
  4819                              <1> 	;xor	dx, dx ; column 0, row 0
  4820                              <1> 	; 02/02/2022
  4821 000042ED 31D2                <1> 	xor	edx, edx
  4822                              <1> 	; 23/02/2022
  4823                              <1> 	;call	set_cpos
  4824                              <1> 	;retn
  4825 000042EF E9DAD1FFFF          <1> 	jmp	set_cpos
  4826                              <1> 
  4827                              <1> 	;mov	al, bl
  4828                              <1> 	;mov	ah, [u.uno]
  4829                              <1> 	;mov	[u.r0], ax
  4830                              <1> 	;jmp	short sysstty_11
  4831                              <1> 
  4832                              <1> ;sysstty_15:
  4833                              <1> ;	; 30/01/2022
  4834                              <1> ;	; permission (denied) error
  4835                              <1> ;	;xor	dl, dl ; sysstty call sign
  4836                              <1> ;	mov	al, cl
  4837                              <1> ;	sub	ah, ah ; 0
  4838                              <1> ;	call	cttyp
  4839                              <1> ;	jmp	error
  4840                              <1> 
  4841                              <1> ; Original UNIX v1 'sysstty' routine:
  4842                              <1> ; gtty:
  4843                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4844                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4845                              <1> 	; 		/ r2 has source
  4846                              <1>         ;mov    r2,-(sp)
  4847                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4848                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4849                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4850                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4851                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4852                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4853                              <1>         ;       br .+4 / list empty, skip branch
  4854                              <1>         ;br     1b / get another character until list is empty
  4855                              <1>         ;mov    0b,r1 / move cc offset to r1
  4856                              <1>         ;inc    r1 / bump it for output clist
  4857                              <1>         ;tstb   cc(r1) / is it 0
  4858                              <1>         ;beq    1f / yes, no characters to output
  4859                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4860                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4861                              <1>         ;br     1b / try to calm it down again
  4862                              <1> ;1:
  4863                              <1>         ;mov    (sp)+,r1
  4864                              <1>         ;mov    (sp)+,r2 / restore registers
  4865                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4866                              <1>         ;beq    1f / if 0, 1f
  4867                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4868                              <1>         ;                   / control status register
  4869                              <1> ;1:
  4870                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4871                              <1>         ;beq    1f / if 0 1f
  4872                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4873                              <1> 	;		    / control status reg
  4874                              <1> ;1:
  4875                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4876                              <1>         ;jmp     sysret2 / return to user
  4877                              <1> 
  4878                              <1> sysgtty: ; < get tty status >
  4879                              <1> 	; 22/02/2022
  4880                              <1> 	; 21/02/2022 
  4881                              <1> 	;	(Retro UNIX 386 v1.2, inode number modifications)
  4882                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4883                              <1> 	;	    ((32 bit reg push/pop))
  4884                              <1> 	; 23/11/2015
  4885                              <1> 	; 29/10/2015
  4886                              <1> 	; 17/10/2015
  4887                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4888                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4889                              <1> 	;
  4890                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4891                              <1> 	; It stores in the three words addressed by it's argument
  4892                              <1> 	; the status of the typewriter whose file descriptor
  4893                              <1> 	; in (u.r0).
  4894                              <1> 	;
  4895                              <1> 	; Calling sequence:
  4896                              <1> 	;	sysgtty; arg
  4897                              <1> 	; Arguments:
  4898                              <1> 	;	arg - address of 3 words destination of the status
  4899                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4900                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4901                              <1> 	; ...............................................................
  4902                              <1> 	;	
  4903                              <1> 	; Retro UNIX 8086 v1 modification: 
  4904                              <1> 	;	'sysgtty' system call will return status of tty
  4905                              <1> 	;	(keyboard, serial port and video page status)
  4906                              <1> 	;	 in following manner:
  4907                              <1> 	;
  4908                              <1> 	; Inputs:
  4909                              <1> 	;	BX = 0 --> means 
  4910                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4911                              <1> 	;	                 for (current) process
  4912                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4913                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4914                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4915                              <1> 	;	     CH > 0 -->	tty number + 1
  4916                              <1> 	;
  4917                              <1> 	;	BX > 0 --> points to name of tty
  4918                              <1> 	;	     CL = 0 --> return keyboard status
  4919                              <1> 	;	     CL = 1 --> return video page status
  4920                              <1> 	;	     CH = undefined		 
  4921                              <1> 	;
  4922                              <1> 	; Outputs:
  4923                              <1> 	;	cf = 0 ->
  4924                              <1> 	;
  4925                              <1> 	;	     AL = tty number from 0 to 9
  4926                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4927                              <1> 	;	     AH = 0 if the tty is free/unused
  4928                              <1> 	;	     AH = the process number of the caller 
  4929                              <1>  	;	     AH = FFh if the tty is locked by another process
  4930                              <1> 	;
  4931                              <1> 	;	  (if calling is for serial port status)
  4932                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4933                              <1> 	;		  (BH = modem status, BL = Line status)
  4934                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4935                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4936                              <1> 	;
  4937                              <1> 	;	  (if calling is for keyboard status)
  4938                              <1> 	;	     BX = current character in tty/keyboard buffer
  4939                              <1> 	;		  (BH = scan code, BL = ascii code)
  4940                              <1> 	;		  (BX=0 if there is not a waiting character)
  4941                              <1> 	;	     CX  is undefined
  4942                              <1> 	;
  4943                              <1> 	;	  (if calling is for video page status)	
  4944                              <1> 	;	     BX = cursor position on the video page
  4945                              <1> 	;		  if tty number < 8
  4946                              <1> 	;		  (BH = row, BL = column)
  4947                              <1> 	;	     CX = current character (in cursor position)
  4948                              <1> 	;		  on the video page of the tty 
  4949                              <1> 	;		  if tty number < 8
  4950                              <1> 	;		  (CH = color, CL = character)
  4951                              <1> 	;	
  4952                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4953                              <1> 	;
  4954                              <1> 	;	     AH = FFh if the caller is not owner of
  4955                              <1> 	;		  specified tty or console tty
  4956                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4957                              <1> 	;	     BX, CX are undefined if cf = 1
  4958                              <1> 	;
  4959                              <1> 	;	  (If tty number is 8 or 9)
  4960                              <1> 	;	     AL = tty number 
  4961                              <1> 	;	     AH = the process number of the caller 
  4962                              <1> 	;	     BX = serial port status
  4963                              <1> 	;  		 (BH = modem status, BL = Line status)
  4964                              <1> 	;	     CX = 0
  4965                              <1> 	;
  4966                              <1> 		
  4967                              <1> gtty:   ; get (requested) tty number
  4968                              <1> 	; 22/02/2022
  4969                              <1> 	; 21/02/2022 (Retro UNIX 386 v1.2, inode number modifications)
  4970                              <1> 	; 17/10/2015
  4971                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4972                              <1> 	; 30/05/2013 - 12/07/2014
  4973                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4974                              <1> 	;
  4975                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4976                              <1> 	;
  4977                              <1> 	; 28/06/2015 (32 bit modifications)
  4978                              <1> 	; 16/01/2014
  4979 000042F4 31C0                <1> 	xor 	eax, eax
  4980 000042F6 6648                <1> 	dec	ax ; 17/10/2015
  4981 000042F8 A3[AC750000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4982 000042FD 80F901              <1> 	cmp	cl, 1
  4983 00004300 760F                <1> 	jna	short sysgtty_0
  4984                              <1> sysgtty_invp:
  4985                              <1> 	; 28/06/2015
  4986 00004302 C705[20760000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4986 0000430A 0000                <1>
  4987 0000430C E937F8FFFF          <1> 	jmp	error
  4988                              <1> sysgtty_0:	
  4989 00004311 21DB                <1> 	and	ebx, ebx
  4990 00004313 7427                <1> 	jz	short sysgtty_1
  4991                              <1> 	;
  4992 00004315 891D[C8750000]      <1> 	mov	[u.namep], ebx
  4993                              <1> 	;push	cx ; 23/11/2015
  4994 0000431B 51                  <1> 	push	ecx ; 24/12/2021
  4995 0000431C E837070000          <1> 	call	namei
  4996 00004321 59                  <1> 	pop	ecx
  4997                              <1> 	;pop	cx ; 23/11/2015
  4998 00004322 7213                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4999                              <1> 	;
  5000                              <1> 	; 21/02/2022
  5001                              <1> 	;cmp	ax, 1
  5002                              <1> 	;jna	short sysgtty_2
  5003                              <1> 	;sub	ax, 10
  5004                              <1> 	;cmp	ax, 9
  5005                              <1> 	;;ja	short sysgtty_inv_dn
  5006                              <1> 	;;mov	ch, al
  5007                              <1> 	;;jmp	short sysgtty_4
  5008                              <1> 	;; 23/11/2015
  5009                              <1> 	;jna	short sysgtty_4
  5010                              <1> 	;
  5011                              <1> 	; 21/02/2022
  5012                              <1> 	; (Retro UNIX 386 v2 file system inode numbers)
  5013 00004324 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  5014 00004327 770E                <1> 	ja	short sysgtty_inv_dn
  5015                              <1> 	;cmp	al, 8	; /dev/tty inode number is 8
  5016                              <1> 	;jb	short sysgtty_inv_dn
  5017 00004329 2C08                <1> 	sub	al, 8
  5018 0000432B 720A                <1> 	jb	short sysgtty_inv_dn
  5019 0000432D 7416                <1> 	jz	short sysgtty_2 ; /dev/tty inode number is 8
  5020                              <1> 	; convert inode number to tty number (tty0 to tty9)
  5021 0000432F 2C09                <1> 	sub	al, 9
  5022 00004331 7204                <1> 	jb	short sysgtty_inv_dn
  5023                              <1> 	; al = 0 to 9
  5024 00004333 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  5025 00004335 EB1F                <1> 	jmp	short sysgtty_4
  5026                              <1> 	
  5027                              <1> sysgtty_inv_dn: 
  5028                              <1> 	;; 28/06/2015
  5029                              <1> 	;; Invalid device name (not a tty) ! error
  5030                              <1> 	;; (Device is not a tty or device name not found)
  5031                              <1> 	;mov	dword [u.error], ERR_INV_DEV_NAME
  5032                              <1> 	;jmp	error
  5033                              <1> 	; 21/02/2022
  5034 00004337 E935FFFFFF          <1> 	jmp	sysstty_inv_dn
  5035                              <1> 
  5036                              <1> sysgtty_1:
  5037                              <1> 	; 16/01/2014
  5038 0000433C 80FD0A              <1> 	cmp	ch, 10
  5039 0000433F 77C1                <1> 	ja	short sysgtty_invp ; 28/06/2015
  5040 00004341 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  5041 00004343 790F                <1> 	jns	short sysgtty_3 ; not negative
  5042                              <1> sysgtty_2:
  5043                              <1> 	; get tty number of console tty
  5044 00004345 8A25[FD750000]      <1> 	mov	ah, [u.uno]
  5045                              <1>  	; 28/06/2015
  5046 0000434B 0FB6DC              <1> 	movzx 	ebx, ah
  5047 0000434E 8AAB[D7710000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  5048                              <1> sysgtty_3:
  5049 00004354 88E8                <1> 	mov	al, ch
  5050                              <1> sysgtty_4:
  5051 00004356 A2[AC750000]        <1> 	mov	[u.r0], al
  5052                              <1>  	; 28/06/2015
  5053                              <1> 	;cmp	al, 9
  5054                              <1> 	;ja	short sysgtty_invp
  5055 0000435B 8B2D[A8750000]      <1> 	mov	ebp, [u.usp]
  5056                              <1> 	; 23/11/2015
  5057 00004361 20C9                <1> 	and	cl, cl
  5058 00004363 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  5059 00004365 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  5060 00004367 722E                <1> 	jb	short sysgtty_6 ; video page status
  5061                              <1> 	; serial port status
  5062                              <1> 	; 12/07/2014
  5063                              <1> 	;mov	dx, 0
  5064                              <1> 	;je	short sysgtty_5
  5065                              <1> 	;inc	dl
  5066                              <1> ;sysgtty_5:
  5067                              <1> 	; 28/06/2015
  5068 00004369 2C08                <1> 	sub	al, 8
  5069 0000436B E808F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  5070                              <1> 	; AL = Line status, AH = Modem status
  5071 00004370 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  5072 00004374 8A25[FD750000]      <1> 	mov	ah, [u.uno]
  5073 0000437A 8825[AD750000]      <1>         mov     [u.r0+1], ah
  5074                              <1> 	; 24/12/2021
  5075 00004380 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  5076                              <1> 				; (in ECX)
  5077 00004386 A880                <1> 	test	al, 80h
  5078 00004388 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  5079 0000438A A801                <1> 	test	al, 1
  5080                              <1> 	;jz	sysret
  5081 0000438C 7404                <1> 	jz	short sysgtty_10
  5082 0000438E 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  5083                              <1> sysgtty_10:
  5084 00004392 E9D1F7FFFF          <1> 	jmp	sysret
  5085                              <1> sysgtty_6:
  5086 00004397 A2[E1750000]        <1> 	mov	[u.ttyn], al ; tty number
  5087                              <1> 	;movzx	ebx, al
  5088 0000439C 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  5089 0000439E D0E3                <1> 	shl 	bl, 1  ; aligned to word
  5090                              <1> 	; 22/04/2014 - 29/06/2015
  5091 000043A0 81C3[E4700000]      <1>         add     ebx, ttyl
  5092 000043A6 8A23                <1>  	mov	ah, [ebx]
  5093 000043A8 3A25[FD750000]      <1> 	cmp	ah, [u.uno]
  5094 000043AE 7404                <1> 	je	short sysgtty_7
  5095 000043B0 20E4                <1> 	and	ah, ah
  5096                              <1> 	;jz	short sysgtty_7
  5097 000043B2 7506                <1> 	jnz	short sysgtty_8
  5098                              <1> 	;mov	ah, 0FFh
  5099                              <1> sysgtty_7:
  5100 000043B4 8825[AD750000]      <1>         mov     [u.r0+1], ah
  5101                              <1> sysgtty_8:
  5102 000043BA 08C9                <1> 	or	cl, cl
  5103 000043BC 7510                <1> 	jnz	short sysgtty_9
  5104 000043BE B001                <1> 	mov	al, 1  ; test a key is available
  5105 000043C0 E853210000          <1> 	call	getc
  5106 000043C5 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  5107 000043C9 E99AF7FFFF          <1> 	jmp	sysret
  5108                              <1> sysgtty_9:
  5109 000043CE 8A1D[E1750000]      <1> 	mov	bl, [u.ttyn]
  5110                              <1> 	; bl = video page number
  5111 000043D4 E8B0220000          <1> 	call 	get_cpos
  5112                              <1> 	; dx = cursor position
  5113 000043D9 66895510            <1> 	mov	[ebp+16], dx ; bx
  5114                              <1> 	;mov	bl, [u.ttyn]
  5115                              <1> 	; bl = video page number
  5116 000043DD E8B8220000          <1> 	call	read_ac_current
  5117                              <1> 	; ax = character and attribute/color
  5118 000043E2 66894518            <1> 	mov	[ebp+24], ax ; cx
  5119 000043E6 E97DF7FFFF          <1> 	jmp	sysret
  5120                              <1> sysgtty_dnr_err:
  5121                              <1> 	; 'device not responding !' error	
  5122                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  5123 000043EB C705[20760000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  5123 000043F3 0000                <1>
  5124 000043F5 E94EF7FFFF          <1> 	jmp	error	
  5125                              <1> 
  5126                              <1> ; Original UNIX v1 'sysgtty' routine:
  5127                              <1> ; sysgtty:
  5128                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  5129                              <1> 	;	       / r2 has destination
  5130                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  5131                              <1> 	;                     / in 1st word of dest
  5132                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  5133                              <1> 	;                     / in 2nd word of dest
  5134                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  5135                              <1>         ;jmp    sysret2 / return to user
  5136                              <1> 	
  5137                              <1> ; Original UNIX v1 'gtty' routine:
  5138                              <1> ; gtty:
  5139                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  5140                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  5141                              <1>         ;jsr    r0,getf / get the i-number of the file
  5142                              <1>         ;tst    r1 / is it open for reading
  5143                              <1>         ;bgt    1f / yes
  5144                              <1>         ;neg    r1 / no, i-number is negative, 
  5145                              <1> 	;          / so make it positive
  5146                              <1> ;1:
  5147                              <1>         ;sub    $14.,r1 / get i-number of tty0
  5148                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  5149                              <1>         ;bhis   error9 / no, error
  5150                              <1>         ;asl    r1 / 0%2
  5151                              <1>         ;asl    r1 / 0%4 / yes
  5152                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  5153                              <1> 	;	       ; / tty block
  5154                              <1>         ;mov    u.off,r2 / put argument in r2
  5155                              <1>         ;rts    r0 / return
  2088                                  %include 'u2.s'      ; 11/05/2015
  2089                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2090                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2091                              <1> ; ****************************************************************************
  2092                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS2.INC
  2093                              <1> ; Last Modification: 26/03/2022
  2094                              <1> ; ----------------------------------------------------------------------------
  2095                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2096                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2097                              <1> ;
  2098                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2099                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2100                              <1> ; <Bell Laboratories (17/3/1972)>
  2101                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2102                              <1> ;
  2103                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2104                              <1> ;
  2105                              <1> ; ****************************************************************************
  2106                              <1> 
  2107                              <1> syslink:
  2108                              <1> 	; 12/01/2022
  2109                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2110                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2111                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2112                              <1> 	;
  2113                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2114                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2115                              <1> 	; given to the entry that will go in the current directory.
  2116                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2117                              <1> 	; in the name 2 entry of current directory is the same
  2118                              <1> 	; i-number for the name 1 file.
  2119                              <1> 	;
  2120                              <1> 	; Calling sequence:
  2121                              <1> 	;	syslink; name 1; name 2
  2122                              <1> 	; Arguments:
  2123                              <1> 	;	name 1 - file name to which link will be created.
  2124                              <1> 	;	name 2 - name of entry in current directory that
  2125                              <1> 	;		 links to name 1.
  2126                              <1> 	; Inputs: -
  2127                              <1> 	; Outputs: -
  2128                              <1> 	; ...............................................................
  2129                              <1> 	;	
  2130                              <1> 	; Retro UNIX 8086 v1 modification: 
  2131                              <1> 	;       'syslink' system call has two arguments; so,
  2132                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2133                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2134                              <1> 	;
  2135                              <1> 		; / name1, name2
  2136                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2137 000043FA 891D[C8750000]      <1> 	mov	[u.namep], ebx
  2138 00004400 51                  <1> 	push	ecx
  2139 00004401 E852060000          <1> 	call	namei
  2140                              <1> 		; jsr r0,namei / find the i-number associated with
  2141                              <1> 			     ; / the 1st path name
  2142                              <1>      	;;and	ax, ax
  2143                              <1> 	;;jz	error ; File not found
  2144                              <1> 	;jc	error 
  2145                              <1> 		; br error9 / cannot be found
  2146 00004406 730F                <1> 	jnc	short syslink0
  2147                              <1> 	;pop 	ecx
  2148                              <1> 	; 'file not found !' error
  2149 00004408 C705[20760000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2149 00004410 0000                <1>
  2150 00004412 E931F7FFFF          <1> 	jmp	error
  2151                              <1> syslink0:
  2152 00004417 E8F9100000          <1> 	call	iget
  2153                              <1> 		; jsr r0,iget / get the i-node into core
  2154 0000441C 8F05[C8750000]      <1> 	pop	dword [u.namep] ; ecx
  2155                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2156                              <1> 	; 24/12/2021
  2157 00004422 50                  <1> 	push	eax ; *
  2158                              <1> 	;push	ax
  2159                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2160                              <1> 			    ; / (a link to this file is to be created)
  2161                              <1> 	; 24/12/2021
  2162 00004423 8A0D[8D750000]      <1> 	mov	cl, [cdev]
  2163 00004429 51                  <1> 	push	ecx ; **
  2164                              <1> 	;push	word [cdev]
  2165                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2166 0000442A E8AC000000          <1> 	call	isdir
  2167                              <1> 		; jsr r0,isdir / is it a directory
  2168 0000442F E824060000          <1> 	call	namei
  2169                              <1> 		; jsr r0,namei / no, get i-number of name2
  2170                              <1> 	;jnc	error
  2171                              <1> 		; br .+4   / not found 
  2172                              <1> 			 ; / so r1 = i-number of current directory
  2173                              <1> 			 ; / ii = i-number of current directory
  2174                              <1> 		; br error9 / file already exists., error
  2175 00004434 720F                <1> 	jc	short syslink1
  2176                              <1> 	; pop eax ; 24/12/2021
  2177                              <1> 	; pop eax
  2178                              <1> 	; 'file exists !' error
  2179 00004436 C705[20760000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2179 0000443E 0000                <1>
  2180 00004440 E903F7FFFF          <1> 	jmp	error
  2181                              <1> syslink1:
  2182                              <1> 	;pop	cx
  2183                              <1> 	; 24/12/2021
  2184 00004445 59                  <1> 	pop	ecx ; **
  2185                              <1> 	;cmp	cx, [cdev]
  2186 00004446 3A0D[8D750000]      <1> 	cmp	cl, [cdev]
  2187                              <1> 	;jne	error
  2188                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2189                              <1> 			       ; / end of current directory
  2190                              <1> 	        ; bne error9
  2191 0000444C 740F                <1> 	je	short syslink2
  2192                              <1> 	; 'not same drive !' error
  2193 0000444E C705[20760000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2193 00004456 0000                <1>
  2194 00004458 E9EBF6FFFF          <1> 	jmp	error
  2195                              <1> syslink2:
  2196                              <1> 	;pop	eax ; 24/12/2021
  2197                              <1> 	;push	eax
  2198                              <1> 	; 24/12/2021
  2199 0000445D 8B0424              <1> 	mov	eax, [esp] ; *
  2200 00004460 66A3[E4750000]      <1> 	mov	[u.dirbuf], ax
  2201                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2202 00004466 E8C5000000          <1> 	call	mkdir
  2203                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2204                              <1> 		 	     ; / in current directory
  2205                              <1> 	; 24/12/2021
  2206 0000446B 58                  <1> 	pop	eax ; *
  2207                              <1> 	;pop	ax
  2208                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2209 0000446C E8A4100000          <1> 	call	iget
  2210                              <1> 		; jsr r0,iget / get i-node into core
  2211 00004471 FE05[5A710000]      <1> 	inc	byte [i.nlks]
  2212                              <1> 		; incb i.nlks / add 1 to its number of links
  2213                              <1> sysunlink_2:
  2214                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2215 00004477 C605[9F750000]01    <1> 	mov	byte [imodx], 1	; (flag means file data is same
  2216                              <1> 				;  but inode's itself has been modified)
  2217 0000447E E823120000          <1> 	call	setimod
  2218                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2219 00004483 E9E0F6FFFF          <1> 	jmp	sysret
  2220                              <1> 
  2221                              <1> sysunlink:
  2222                              <1> 	; 12/01/2022
  2223                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2224                              <1> 	; 04/12/2015 (14 byte file names)
  2225                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2226                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2227                              <1> 	;
  2228                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2229                              <1> 	; name from its directory. If this entry was the last link
  2230                              <1> 	; to the file, the contents of the file are freed and the
  2231                              <1> 	; file is destroyed. If, however, the file was open in any
  2232                              <1> 	; process, the actual destruction is delayed until it is 
  2233                              <1> 	; closed, even though the directory entry has disappeared.
  2234                              <1> 	; 
  2235                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2236                              <1> 	; does not exist or that its directory can not be written.
  2237                              <1> 	; Write permission is not required on the file itself.
  2238                              <1> 	; It is also illegal to unlink a directory (except for
  2239                              <1> 	; the superuser).
  2240                              <1> 	;
  2241                              <1> 	; Calling sequence:
  2242                              <1> 	;	sysunlink; name
  2243                              <1> 	; Arguments:
  2244                              <1> 	;	name - name of directory entry to be removed 
  2245                              <1> 	; Inputs: -
  2246                              <1> 	; Outputs: -
  2247                              <1> 	; ...............................................................
  2248                              <1> 	;				
  2249                              <1> 	; Retro UNIX 8086 v1 modification:
  2250                              <1> 	;	 The user/application program puts address of the name
  2251                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2252                              <1> 
  2253                              <1> 	; / name - remove link name
  2254 00004488 891D[C8750000]      <1> 	mov	[u.namep], ebx
  2255                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2256 0000448E E8C5050000          <1> 	call	namei
  2257                              <1> 		; jsr r0,namei / find the i-number associated 
  2258                              <1> 			     ; / with the path name
  2259                              <1> 	;jc	error
  2260                              <1> 		; br error9 / not found
  2261 00004493 730F                <1> 	jnc	short sysunlink1
  2262                              <1> 	; 'file not found !' error
  2263 00004495 C705[20760000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2263 0000449D 0000                <1>
  2264 0000449F E9A4F6FFFF          <1> 	jmp	error
  2265                              <1> sysunlink1:
  2266 000044A4 50                  <1> 	push	eax ; 24/12/2021
  2267                              <1> 	;push	ax
  2268                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2269 000044A5 E831000000          <1> 	call	isdir
  2270                              <1> 		; jsr r0,isdir / is it a directory
  2271                              <1> 	;xor 	ax, ax
  2272                              <1> 	; 24/12/2021
  2273 000044AA 31C0                <1> 	xor	eax, eax
  2274 000044AC 66A3[E4750000]      <1> 	mov	[u.dirbuf], ax ; 0
  2275                              <1> 		; clr u.dirbuf / no, clear the location that will
  2276                              <1> 			   ; / get written into the i-number portion
  2277                              <1> 			 ; / of the entry
  2278 000044B2 832D[CC750000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2279                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2280 000044B9 E8BD000000          <1> 	call	wdir
  2281                              <1> 		; jsr r0,wdir / free the directory entry
  2282 000044BE 58                  <1> 	pop	eax ; 24/12/2021
  2283                              <1> 	;pop	ax
  2284                              <1> 		; mov (sp)+,r1 / get i-number back
  2285 000044BF E851100000          <1> 	call	iget
  2286                              <1> 		; jsr r0,iget / get i-node
  2287                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2288                              <1> 	;call	setimod
  2289                              <1> 	;	; jsr r0,setimod / set modified flag
  2290                              <1> 	;	
  2291 000044C4 FE0D[5A710000]      <1> 	dec	byte [i.nlks]
  2292                              <1> 		; decb i.nlks / decrement the number of links
  2293                              <1> 	; 24/12/2021
  2294 000044CA 75AB                <1> 	jnz	short sysunlink_2
  2295                              <1> 	;jnz	sysret
  2296                              <1> 		; bgt sysret9 / if this was not the last link
  2297                              <1> 			    ; / to file return
  2298                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2299 000044CC E8D5110000          <1> 	call	setimod
  2300                              <1> 		; jsr r0,setimod / set modified flag
  2301                              <1> 	; AX = r1 = i-number
  2302 000044D1 E84D0A0000          <1> 	call	anyi
  2303                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2304                              <1> 			 ; / Then free contents of file and destroy it.
  2305 000044D6 E98DF6FFFF          <1> 	jmp	sysret
  2306                              <1> 		; br sysret9
  2307                              <1> ;sysunlink_2:
  2308                              <1> 	;; 12/01/2022 - Retro UNIX 386 v1.2
  2309                              <1> 	;mov	byte [imodx], 1	; (flag means file data is same
  2310                              <1> 	;			;  but inode's itself has been modified)
  2311                              <1> 	;call	setimod
  2312                              <1> 	;	; jsr r0,setimod / set the i-node modified flag
  2313                              <1> 	;jmp	sysret
  2314                              <1> 
  2315                              <1> isdir:
  2316                              <1> 	; 13/03/2022
  2317                              <1> 	; 08/01/2022
  2318                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  2319                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2320                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2321                              <1> 	;
  2322                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2323                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2324                              <1> 	;  called by syslink and sysunlink to make sure directories
  2325                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2326                              <1> 	; 'isdir' does not bother checking. The current i-node
  2327                              <1> 	;  is not disturbed.			
  2328                              <1> 	;		
  2329                              <1> 	; INPUTS ->
  2330                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2331                              <1> 	;    u.uid - user id
  2332                              <1> 	; OUTPUTS ->
  2333                              <1> 	;    r1 - contains current i-number upon exit
  2334                              <1> 	;    	 (current i-node back in core) 
  2335                              <1> 	;	
  2336                              <1> 	; ((AX = R1))
  2337                              <1> 	;
  2338                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2339                              <1> 	;
  2340                              <1> 
  2341                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2342                              <1> 	; / there is an error unless super user made the call
  2343                              <1> 	
  2344                              <1> 	; 01/01/2022
  2345 000044DB 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0 ; 16 bit uid (runix v2 fs inode)
  2346                              <1> 	;cmp	byte [u.uid], 0 
  2347                              <1> 		; tstb u.uid / super user
  2348 000044E3 764A                <1> 	jna	short isdir1
  2349                              <1> 		; beq 1f / yes, don't care
  2350                              <1> 	; 08/01/2022
  2351 000044E5 FF35[88750000]      <1> 	push	dword [ii]
  2352                              <1> 	;push	word [ii]
  2353                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2354 000044EB E825100000          <1> 	call	iget
  2355                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2356                              <1> 	; 01/01/2022 (runix v2 fs inode flags)
  2357 000044F0 F605[59710000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  2358 000044F7 7421                <1> 	jz	short isdir2 ; no, error!
  2359 000044F9 F605[59710000]40    <1> 	test	byte [i.flgs+1], 40h ; directory flag
  2360                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2361                              <1> 		; bit $40000,i.flgs / is it a directory
  2362                              <1> 	;jnz	error
  2363                              <1> 		; bne error9 / yes, error
  2364 00004500 7427                <1> 	jz	short isdir0
  2365                              <1> 
  2366                              <1> 	; 13/03/2022
  2367                              <1> 	; NOTE:
  2368                              <1> 	; Unix v5-v7 kernels do not allow (ordinary) users
  2369                              <1> 	; (except root/superuser) --if [u.uid] > 0--
  2370                              <1> 	; to link a directory. (ref: sys2.c, 'link')
  2371                              <1> 	;
  2372                              <1> 	; But, Retro UNIX 386 v1.2 will allow the owner of
  2373                              <1> 	; the directory to link it.
  2374                              <1> 
  2375 00004502 66A1[5C710000]      <1> 	mov	ax, [i.uid] ; owner ID of the parent dir
  2376 00004508 663B05[FE750000]    <1> 	cmp	ax, [u.uid] ; user ID of current user/process
  2377 0000450F 7509                <1> 	jne	short isdir2
  2378                              <1> 	; 13/03/2022
  2379                              <1> 	; additional checking (may or may not be necessary!?)
  2380 00004511 663B05[00760000]    <1> 	cmp	ax, [u.ruid] 
  2381                              <1> 			; real (login) user ID must be same
  2382 00004518 740F                <1> 	je	short isdir0
  2383                              <1> 
  2384                              <1> isdir2:
  2385 0000451A C705[20760000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2385 00004522 0000                <1>
  2386                              <1> 				; 'permission denied !' error
  2387                              <1> 	;pop	ax
  2388 00004524 E91FF6FFFF          <1> 	jmp	error	
  2389                              <1> isdir0:	
  2390                              <1> 	; 08/01/2022
  2391 00004529 58                  <1> 	pop	eax
  2392                              <1> 	;pop	ax
  2393                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2394 0000452A E8E60F0000          <1> 	call	iget
  2395                              <1> 		; jsr r0,iget / get it back in
  2396                              <1> isdir1: ; 1:
  2397 0000452F C3                  <1> 	retn
  2398                              <1> 		; rts r0
  2399                              <1> 
  2400                              <1> mkdir:
  2401                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2402                              <1> 	; 04/12/2015 (14 byte directory names)
  2403                              <1> 	; 12/10/2015
  2404                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2405                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2406                              <1> 	;
  2407                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2408                              <1> 	; by u.namep into the current directory.
  2409                              <1> 	;
  2410                              <1> 	; INPUTS ->
  2411                              <1> 	;    u.namep - points to a file name 
  2412                              <1> 	;	           that is about to be a directory entry.
  2413                              <1> 	;    ii - current directory's i-number.	
  2414                              <1> 	; OUTPUTS ->
  2415                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2416                              <1> 	;    u.off - points to entry to be filled 
  2417                              <1> 	;	     in the current directory		
  2418                              <1> 	;    u.base - points to start of u.dirbuf.
  2419                              <1> 	;    r1 - contains i-number of current directory 
  2420                              <1> 	;	
  2421                              <1> 	; ((AX = R1)) output
  2422                              <1> 	;
  2423                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2424                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2425                              <1> 	;
  2426                              <1> 
  2427                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2428 00004530 31C0                <1> 	xor 	eax, eax
  2429 00004532 BF[E6750000]        <1> 	mov     edi, u.dirbuf+2
  2430 00004537 89FE                <1> 	mov	esi, edi
  2431 00004539 AB                  <1> 	stosd
  2432 0000453A AB                  <1> 	stosd
  2433                              <1> 	; 04/12/2015 (14 byte directory names)
  2434 0000453B AB                  <1> 	stosd
  2435 0000453C 66AB                <1> 	stosw
  2436                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2437 0000453E 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2438                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2439                              <1> 	;mov 	ebp, [u.namep]
  2440 00004540 E831060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2441                              <1> 		; esi = physical address (page start + offset)
  2442                              <1> 		; ecx = byte count in the page (1 - 4096)
  2443                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2444                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2445                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2446                              <1> mkdir_1: ; 1: 
  2447 00004545 45                  <1> 	inc	ebp ; 12/10/2015
  2448                              <1> 	;
  2449                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2450                              <1> 	; 01/08/2013
  2451 00004546 AC                  <1> 	lodsb
  2452                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2453 00004547 20C0                <1> 	and 	al, al
  2454 00004549 7426                <1> 	jz 	short mkdir_3 	  
  2455                              <1> 		; beq 1f / if null, done
  2456 0000454B 3C2F                <1> 	cmp	al, '/'
  2457                              <1> 		; cmp r1,$'/ / is it a "/"?
  2458 0000454D 7413                <1> 	je	short mkdir_err
  2459                              <1> 	;je	error
  2460                              <1> 		; beq error9 / yes, error
  2461                              <1> 	; 12/10/2015
  2462                              <1> 	;dec	cx
  2463 0000454F 49                  <1> 	dec	ecx ; 24/12/2021
  2464 00004550 7505                <1> 	jnz	short mkdir_2
  2465                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2466 00004552 E825060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2467                              <1> 		; esi = physical address (page start + offset)
  2468                              <1> 		; ecx = byte count in the page
  2469                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2470                              <1> mkdir_2:
  2471 00004557 81FF[F4750000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2472                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2473                              <1> 				     ; / a char?
  2474 0000455D 74E6                <1> 	je	short mkdir_1
  2475                              <1> 		; beq 1b / yes, go back
  2476 0000455F AA                  <1> 	stosb
  2477                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2478 00004560 EBE3                <1> 	jmp 	short mkdir_1
  2479                              <1> 		; br 1b / get next char
  2480                              <1> mkdir_err:
  2481                              <1> 	; 17/06/2015
  2482 00004562 C705[20760000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2482 0000456A 0000                <1>
  2483 0000456C E9D7F5FFFF          <1> 	jmp	error
  2484                              <1> 
  2485                              <1> mkdir_3: ; 1:
  2486 00004571 A1[C4750000]        <1> 	mov	eax, [u.dirp]
  2487 00004576 A3[CC750000]        <1> 	mov	[u.off], eax
  2488                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2489                              <1> 				 ; / slot to u.off
  2490                              <1> 	; 08/01/2022
  2491                              <1> wdir:	; 24/12/2021 (Retro UNIX 386 v1.2)
  2492                              <1> 	; 29/04/2013
  2493 0000457B C705[D0750000]-     <1>         mov     dword [u.base], u.dirbuf
  2493 00004581 [E4750000]          <1>
  2494                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2495 00004585 C705[D4750000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2495 0000458D 0000                <1>
  2496                              <1> 		; mov $10.,u.count / u.count = 10
  2497                              <1> 	; 08/01/2022
  2498 0000458F A1[88750000]        <1> 	mov	eax, [ii]
  2499                              <1> 	;mov	ax, [ii] 
  2500                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2501                              <1> 	;mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2502                              <1> 	; 08/01/2022 (Retro UNIX 386 v2 file system inode)
  2503 00004594 66BA8000            <1> 	mov	dx, 80h	; mov dx, IWRITE
  2504 00004598 E862100000          <1> 	call 	access
  2505                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2506                              <1> 				 ; / for writing
  2507                              <1> 	; AX = i-number of current directory
  2508                              <1> 	; 01/08/2013
  2509 0000459D FE05[1E760000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2510                              <1> 	;call	writei
  2511                              <1> 	;	; jsr r0,writei / write into directory
  2512                              <1> 	;retn	
  2513                              <1> 	;	; rts r0
  2514                              <1> 	; 24/12/2021
  2515 000045A3 E9E9140000          <1> 	jmp	writei
  2516                              <1> 
  2517                              <1> 	; 06/02/2022
  2518                              <1> 	; 12/01/2022
  2519                              <1> 	; 01/01/2022
  2520                              <1> 	; 24/12/2021
  2521                              <1> 	; 11/12/2021
  2522                              <1> 	; 04/12/2021
  2523                              <1> 	; 30/11/2021
  2524                              <1> 	; 28/11/2021 - Retro UNIX 386 v1.2
  2525                              <1> 	;	(Retro UNIX 386 v2 fs compatibility modification)
  2526                              <1> sysexec:
  2527                              <1> 	; 02/05/2021
  2528                              <1> 	; 27/03/2021
  2529                              <1> 	; 26/03/2021
  2530                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  2531                              <1> 	; 23/10/2015
  2532                              <1> 	; 10/10/2015, 18/10/2015, 19/10/2015
  2533                              <1> 	; 29/07/2015, 05/08/2015, 05/08/2015
  2534                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2535                              <1> 	; 01/07/2015, 02/07/2015, 20/07,2015
  2536                              <1> 	; 24/06/2015, 25/06/2021
  2537                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2538                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2539                              <1> 	;
  2540                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2541                              <1> 	; pointed to by 'name' in the sysexec call. 
  2542                              <1> 	; 'sysexec' performs the following operations:
  2543                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2544                              <1> 	;    2. obtains i-node of file to be executed via 'iget'.
  2545                              <1> 	;    3. sets trap vectors to system routines.
  2546                              <1> 	;    4. loads arguments to be passed to executing file into
  2547                              <1> 	;	highest locations of user's core
  2548                              <1> 	;    5. puts pointers to arguments in locations immediately
  2549                              <1> 	;	following arguments.
  2550                              <1> 	;    6.	saves number of arguments in next location.
  2551                              <1> 	;    7. initializes user's stack area so that all registers
  2552                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2553                              <1> 	;	to core when 'sysret' restores registers 
  2554                              <1> 	;	and does an rti.
  2555                              <1> 	;    8. inializes u.r0 and u.sp
  2556                              <1> 	;    9. zeros user's core down to u.r0
  2557                              <1> 	;   10.	reads executable file from storage device into core
  2558                              <1> 	;	starting at location 'core'.
  2559                              <1> 	;   11.	sets u.break to point to end of user's code with
  2560                              <1> 	;	data area appended.
  2561                              <1> 	;   12.	calls 'sysret' which returns control at location
  2562                              <1> 	;	'core' via 'rti' instruction.
  2563                              <1> 	;
  2564                              <1> 	; Calling sequence:
  2565                              <1> 	;	sysexec; namep; argp
  2566                              <1> 	; Arguments:
  2567                              <1> 	;	namep - points to pathname of file to be executed
  2568                              <1> 	;	argp  - address of table of argument pointers
  2569                              <1> 	;	argp1... argpn - table of argument pointers
  2570                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2571                              <1> 	; Inputs: (arguments)
  2572                              <1> 	; Outputs: -	
  2573                              <1> 	; ...............................................................
  2574                              <1> 	;
  2575                              <1> 	; Retro UNIX 386 v1 modification: 
  2576                              <1> 	;	User application runs in it's own virtual space 
  2577                              <1> 	;	which is izolated from kernel memory (and other
  2578                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2579                              <1> 	;	privilige mode. Virtual start address is always 0.
  2580                              <1> 	;	User's core memory starts at linear address 400000h
  2581                              <1> 	;	(the end of the 1st 4MB).
  2582                              <1> 	;
  2583                              <1> 	; Retro UNIX 8086 v1 modification: 
  2584                              <1> 	;	user/application segment and system/kernel segment
  2585                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2586                              <1> 	;	are different (user's registers are saved to 
  2587                              <1> 	;	and then restored from system's stack.)
  2588                              <1> 	;
  2589                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2590                              <1> 	;	      arguments which were in these registers;
  2591                              <1> 	;	      but, it returns by putting the 1st argument
  2592                              <1> 	;	      in 'u.namep' and the 2nd argument
  2593                              <1> 	;	      on top of stack. (1st argument is offset of the
  2594                              <1> 	;	      file/path name in the user's program segment.)
  2595                              <1> 	
  2596                              <1> 	;call	arg2
  2597                              <1> 	; * name - 'u.namep' points to address of file/path name
  2598                              <1> 	;          in the user's program segment ('u.segmnt')
  2599                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2600                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2601                              <1> 	;          which is on top of stack.
  2602                              <1> 	;
  2603                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2604                              <1> 
  2605                              <1> 	; 23/06/2015 (32 bit modifications)
  2606                              <1> 
  2607 000045A8 891D[C8750000]      <1> 	mov	[u.namep], ebx ; argument 1
  2608                              <1>         ; 18/10/2015
  2609 000045AE 890D[3C760000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2610 000045B4 E89F040000          <1> 	call	namei
  2611                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2612                              <1> 			     ; / named in sysexec call in r1
  2613                              <1> 	;jc	error
  2614                              <1> 		; br error9
  2615 000045B9 730F                <1> 	jnc	short sysexec_0
  2616                              <1> 	;
  2617                              <1> 	; 'file not found !' error
  2618 000045BB C705[20760000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2618 000045C3 0000                <1>
  2619 000045C5 E97EF5FFFF          <1> 	jmp	error
  2620                              <1> 
  2621                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2622                              <1> 	; (executable file flag is checked in 'access')
  2623                              <1> 	; (following error message is in 'access' subroutine)
  2624                              <1> ;sysexec_not_exf:
  2625                              <1> 	;; 'not executable file !' error
  2626                              <1> 	;mov	dword [u.error], ERR_NOT_EXECUTABLE
  2627                              <1> 	;jmp	error 
  2628                              <1> sysexec_0:
  2629                              <1> 	; 26/03/2021 ('iget' will be called in 'access')
  2630                              <1> 	;call	iget
  2631                              <1> 	;	; jsr r0,iget / get i-node for file to be executed
  2632                              <1> 	;
  2633                              <1> 	;test	byte [i.flgs], 10h
  2634                              <1> 	;;test	word [i.flgs], 10h
  2635                              <1> 	;	; bit $20,i.flgs / is file executable
  2636                              <1> 	;jz	short sysexec_not_exf
  2637                              <1> 	;;jz	error
  2638                              <1> 	;	; beq error9
  2639                              <1> 	; 26/03/2021
  2640 000045CA 66BA4000            <1> 	mov	dx, 40h ; IEXEC - execute, owner
  2641 000045CE E82C100000          <1> 	call	access
  2642                              <1> 	; ! we are here because there is execute permission !
  2643                              <1> 	; ('iopen' is not needed for regular files, from now on)
  2644                              <1> 
  2645                              <1> 	; 26/03/2021
  2646                              <1> 	;; 25/03/2021
  2647                              <1> 	;; (ref: Retro UNIX 386 v2, 'ux.s')
  2648                              <1> 	;mov	dx, 40h ; IEXEC - execute, owner
  2649                              <1> 	;;
  2650                              <1> 	;call	iopen
  2651                              <1> 	;	; jsr r0,iopen / gets i-node for file with i-number
  2652                              <1> 	;		     ; / given in r1 (opens file)
  2653                              <1> 	
  2654                              <1> 	; 26/03/2021
  2655                              <1> 	; AX = i-number of the file
  2656                              <1> 	;test	byte [i.flgs], 20h
  2657                              <1> 	;;test	word [i.flgs], 20h
  2658                              <1> 	;	; bit $40,i.flgs / test user id on execution bit
  2659                              <1> 	;jz	short sysexec_1
  2660                              <1> 	;	; beq 1f
  2661                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013
  2662                              <1> 	;	; tstb u.uid / test user id
  2663                              <1> 	;jna	short sysexec_1
  2664                              <1> 	;	; beq 1f / super user
  2665                              <1> 
  2666                              <1> 	;mov	cl, [i.uid]
  2667                              <1> 	;mov	[u.uid], cl ; 02/08/2013
  2668                              <1> 	;	; movb i.uid,u.uid / put user id of owner of file
  2669                              <1> 				 ; / as process user id
  2670                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2671                              <1> 	;mov	al, [i.flgs+1]
  2672 000045D3 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0	; super user (root) ?
  2673                              <1> 	;jna	short sysexec_19 ; yes, super user
  2674                              <1> 	;; 02/05/2021
  2675 000045DB 7625                <1> 	jna	short sysexec_1	; don't set UID or GID
  2676                              <1> 
  2677                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2
  2678 000045DD A0[59710000]        <1> 	mov	al, [i.flgs+1]
  2679                              <1> 
  2680                              <1> 	; test set user id on execution bit 
  2681 000045E2 A808                <1> 	test	al, 08h ; ISUID flag (800h)
  2682                              <1> 	;jz	short sysexec_19
  2683                              <1> 	; 02/05/2021
  2684 000045E4 741C                <1> 	jz	short sysexec_1 ; do not set group ID
  2685                              <1> 				; (if user ID will not be set)
  2686                              <1> 				; (02/05/2021)	
  2687                              <1> 	; set user id on exec (800h)
  2688                              <1> 	; 26/03/2021
  2689                              <1> sysexec_setuid:
  2690                              <1> 	;; 27/03/2021
  2691                              <1> 	;cmp	word [u.uid], 0
  2692                              <1> 	;;jna	short sysexec_19 ; super user
  2693                              <1> 	;; 02/05/2021
  2694                              <1> 	;jna	short sysexec_1 ; do not set group ID
  2695                              <1> 	;			; (if user ID will not be set)
  2696                              <1> 	;			; (02/05/2021)
  2697 000045E6 668B0D[5C710000]    <1> 	mov	cx, [i.uid]
  2698 000045ED 66890D[FE750000]    <1> 	mov	[u.uid], cx
  2699                              <1> sysexec_19:
  2700                              <1> 	; test set group id on execution bit 
  2701 000045F4 A804                <1> 	test	al, 04h ; ISGID flag (400h)
  2702 000045F6 740A                <1> 	jz	short sysexec_1
  2703                              <1> sysexec_setgid:
  2704                              <1> 	; set group id on exec (400h)
  2705 000045F8 A0[5E710000]        <1> 	mov	al, [i.gid]
  2706 000045FD A2[02760000]        <1> 	mov	[u.gid], al
  2707                              <1> 	;
  2708                              <1> sysexec_1:
  2709                              <1> 	; 06/02/2022
  2710                              <1> 	; 12/01/2022
  2711                              <1> 	; 24/12/2021
  2712                              <1> 	; 11/12/2021
  2713                              <1> 	; 04/12/2021
  2714                              <1> 	; 10/10/2015, 18/10/2015
  2715                              <1> 	; 21/07/2015, 24/07/2015
  2716                              <1> 	; 24/06/2015, 25/06/2015
  2717                              <1>         ; Moving arguments to the end of [u.upage]
  2718                              <1> 	; (by regarding page borders in user's memory space)
  2719                              <1> 	;
  2720                              <1> 	; 10/10/2015
  2721                              <1> 	; 21/07/2015
  2722 00004602 89E5                <1> 	mov	ebp, esp ; (**)
  2723                              <1> 	; 18/10/2015
  2724 00004604 89EF                <1> 	mov 	edi, ebp
  2725 00004606 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2726                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2727 0000460B 29CF                <1> 	sub	edi, ecx
  2728 0000460D 89FC                <1> 	mov	esp, edi
  2729 0000460F 31C0                <1> 	xor	eax, eax
  2730 00004611 A3[D8750000]        <1> 	mov 	[u.nread], eax ; 0
  2731                              <1> 	; 12/01/2022
  2732                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2733                              <1> 	; may leave it with any value after an error))
  2734 00004616 A3[38760000]        <1> 	mov	[argc], eax ; 0
  2735                              <1> 	;
  2736 0000461B 49                  <1> 	dec	ecx ; 256 - 1
  2737 0000461C 890D[D4750000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2738                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2739                              <1> 	; 24/12/2021
  2740                              <1> sysexec_2:
  2741 00004622 8B35[3C760000]      <1> 	mov	esi, [argv] ; 18/10/2015
  2742 00004628 E859020000          <1> 	call	get_argp
  2743                              <1> 	;mov	ecx, 4 
  2744                              <1> 	; 06/02/2022
  2745 0000462D 31C9                <1> 	xor	ecx, ecx
  2746 0000462F B104                <1> 	mov	cl, 4
  2747                              <1> sysexec_3:
  2748 00004631 21C0                <1> 	and	eax, eax
  2749 00004633 7454                <1> 	jz	short sysexec_6
  2750                              <1> 	; 18/10/2015
  2751 00004635 010D[3C760000]      <1> 	add	[argv], ecx ; 4
  2752                              <1> 	;;inc	word [argc]
  2753                              <1> 	; 11/12/2021
  2754                              <1> 	;inc	dword [argc]
  2755                              <1> 	; 12/01/2022
  2756 0000463B FE05[38760000]      <1> 	inc	byte [argc]
  2757                              <1> 	;
  2758 00004641 A3[D0750000]        <1> 	mov	[u.base], eax
  2759                              <1>  	; 23/10/2015
  2760 00004646 66C705[18760000]00- <1> 	mov	word [u.pcount], 0
  2760 0000464E 00                  <1>
  2761                              <1> sysexec_4:
  2762 0000464F E8F8150000          <1> 	call	cpass ; get a character from user's core memory
  2763 00004654 750B                <1>         jnz	short sysexec_5
  2764                              <1> 		; (max. 255 chars + null)
  2765                              <1> 	; 18/10/2015
  2766 00004656 28C0                <1> 	sub 	al, al
  2767 00004658 AA                  <1> 	stosb
  2768 00004659 FF05[D8750000]      <1> 	inc	dword [u.nread]
  2769 0000465F EB28                <1> 	jmp	short sysexec_6
  2770                              <1> sysexec_5:
  2771 00004661 AA                  <1> 	stosb
  2772 00004662 20C0                <1> 	and 	al, al
  2773 00004664 75E9                <1> 	jnz	short sysexec_4
  2774 00004666 B904000000          <1> 	mov	ecx, 4
  2775 0000466B 390D[34760000]      <1> 	cmp	[ncount], ecx ; 4
  2776 00004671 72AF                <1> 	jb	short sysexec_2
  2777 00004673 8B35[30760000]      <1> 	mov	esi, [nbase]
  2778 00004679 010D[30760000]      <1> 	add	[nbase], ecx ; 4	
  2779                              <1> 	;sub	[ncount], cx 
  2780                              <1> 	; 11/12/2021
  2781 0000467F 290D[34760000]      <1> 	sub	[ncount], ecx
  2782 00004685 8B06                <1> 	mov	eax, [esi]
  2783 00004687 EBA8                <1> 	jmp	short sysexec_3
  2784                              <1> sysexec_6:
  2785                              <1> 	; 24/12/2021
  2786                              <1> 	; 18/10/2015
  2787                              <1> 	; argument list transfer from user's core memory to
  2788                              <1> 	; kernel stack frame is OK here.
  2789                              <1> 	; [u.nread] = argument list length
  2790                              <1> 	;mov	[argv], esp ; start address of argument list
  2791                              <1> 	;
  2792                              <1> 	; 18/10/2015
  2793                              <1> 	; 24/07/2015
  2794                              <1>         ; 21/07/2015
  2795                              <1> 	; 02/07/2015
  2796                              <1> 	; 25/06/2015
  2797                              <1> 	; 24/06/2015
  2798                              <1> 	; 23/06/2015
  2799                              <1> 	;
  2800 00004689 8B1D[10760000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2801 0000468F 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2802 00004691 740A                <1> 	jz	short sysexec_7
  2803 00004693 A1[0C760000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2804 00004698 E847E8FFFF          <1> 	call	deallocate_page_dir
  2805                              <1> sysexec_7:
  2806 0000469D E877E7FFFF          <1> 	call	make_page_dir
  2807                              <1> 	;jc	short sysexec_14
  2808                              <1> 	;jc	panic  ; allocation error 
  2809                              <1> 	;	       ; after a deallocation would be nonsence !?
  2810                              <1> 	; 26/03/2021
  2811 000046A2 7243                <1> 	jc	short sysexec_panic
  2812                              <1> 	
  2813                              <1> 	; 24/07/2015
  2814                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2815                              <1> 	;     of the user's page directory
  2816                              <1> 	;     (It is needed for interrupts!)
  2817                              <1> 	; 18/10/2015
  2818 000046A4 8B15[98700000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2819 000046AA 8B02                <1> 	mov	eax, [edx] ; physical address of
  2820                              <1> 			   ; kernel's first page table (1st 4 MB)
  2821                              <1> 			   ; (PDE 0 of kernel's page directory)
  2822 000046AC 8B15[0C760000]      <1> 	mov 	edx, [u.pgdir]
  2823 000046B2 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2824                              <1> 	;
  2825                              <1> 	; 20/07/2015
  2826 000046B4 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2827                              <1> 	; 18/10/2015
  2828 000046B9 BE[28760000]        <1> 	mov	esi, pcore ; physical start address
  2829                              <1> sysexec_8:	
  2830 000046BE B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2831 000046C3 E86FE7FFFF          <1> 	call	make_page_table
  2832                              <1> 	;jc	panic
  2833                              <1> 	; 26/03/2021
  2834 000046C8 721D                <1> 	jc	short sysexec_panic
  2835                              <1> 	;
  2836                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2837 000046CA E876E7FFFF          <1> 	call	make_page ; make new page, clear and set the pte
  2838                              <1> 	;jc	panic
  2839                              <1> 	; 26/03/2021
  2840 000046CF 7216                <1> 	jc	short sysexec_panic
  2841                              <1> 	;
  2842 000046D1 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2843                              <1> 	; ebx = virtual address (24/07/2015)
  2844                              <1> 	; 30/11/2021
  2845                              <1> 	;call 	add_to_swap_queue
  2846                              <1> 	; 18/10/2015
  2847 000046D3 81FE[2C760000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2848 000046D9 7411                <1> 	je	short sysexec_9 ; yes
  2849 000046DB BE[2C760000]        <1> 	mov	esi, ecore  ; physical address of the last page
  2850                              <1> 	; 20/07/2015
  2851 000046E0 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2852                              <1> 	; ebx = virtual end address + segment base address - 4K
  2853 000046E5 EBD7                <1>         jmp     short sysexec_8
  2854                              <1> sysexec_panic:
  2855                              <1> 	; 26/03/2021
  2856 000046E7 E998ECFFFF          <1> 	jmp	panic
  2857                              <1> 
  2858                              <1> sysexec_9:
  2859                              <1> 	; 12/01/2022
  2860                              <1> 	; 11/12/2021
  2861                              <1> 	; 18/10/2015
  2862                              <1> 	; 26/08/2015
  2863                              <1> 	; 25/06/2015
  2864                              <1> 	; move arguments from kernel stack to [ecore]
  2865                              <1> 	; (argument list/line will be copied from kernel stack
  2866                              <1> 	; frame to the last (stack) page of user's core memory)
  2867                              <1> 	; 18/10/2015
  2868 000046EC 8B3D[2C760000]      <1> 	mov	edi, [ecore]
  2869 000046F2 81C700100000        <1> 	add	edi, PAGE_SIZE
  2870                              <1> 	;movzx	eax, word [argc]
  2871                              <1> 	; 12/01/2022
  2872                              <1> 	;xor	eax, eax
  2873                              <1> 	;mov	al, [argc]
  2874                              <1> 	; [argc] < 32
  2875                              <1> 	; 11/12/2021
  2876 000046F8 A1[38760000]        <1> 	mov	eax, [argc]
  2877 000046FD 09C0                <1> 	or	eax, eax
  2878 000046FF 7509                <1> 	jnz	short sysexec_10
  2879 00004701 89FB                <1> 	mov 	ebx, edi
  2880 00004703 83EB04              <1> 	sub	ebx, 4 
  2881 00004706 8903                <1> 	mov	[ebx], eax ; 0
  2882 00004708 EB40                <1> 	jmp 	short sysexec_13
  2883                              <1> sysexec_10:
  2884 0000470A 8B0D[D8750000]      <1> 	mov	ecx, [u.nread]
  2885                              <1> 	;mov 	esi, [argv]
  2886 00004710 89E6                <1> 	mov	esi, esp ; start address of argument list
  2887 00004712 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2888 00004714 89C2                <1> 	mov	edx, eax ; [argc]
  2889 00004716 FEC2                <1> 	inc	dl ; argument count + 1 for argc value  
  2890 00004718 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2891                              <1> 	; max. value of [argc] = 31 (32*4=128)  
  2892                              <1> 	; 12/01/2022
  2893                              <1> 	;inc	edx  ; [argc] <= 255
  2894                              <1> 	;shl	edx, 2 ; max. 256*4
  2895 0000471B 89FB                <1> 	mov	ebx, edi
  2896 0000471D 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2897 00004720 29D3                <1> 	sub 	ebx, edx
  2898 00004722 89FA                <1> 	mov	edx, edi
  2899 00004724 F3A4                <1> 	rep	movsb
  2900 00004726 89D6                <1> 	mov 	esi, edx
  2901 00004728 89DF                <1> 	mov 	edi, ebx
  2902 0000472A BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2903 0000472F 2B15[2C760000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2904 00004735 AB                  <1> 	stosd	; eax = argument count
  2905                              <1> sysexec_11:
  2906 00004736 89F0                <1> 	mov	eax, esi
  2907 00004738 01D0                <1> 	add	eax, edx
  2908 0000473A AB                  <1> 	stosd  ; eax = virtual address
  2909 0000473B FE0D[38760000]      <1> 	dec	byte [argc]
  2910 00004741 7407                <1> 	jz	short sysexec_13
  2911                              <1> sysexec_12:
  2912 00004743 AC                  <1> 	lodsb
  2913 00004744 20C0                <1> 	and	al, al
  2914 00004746 75FB                <1> 	jnz	short sysexec_12
  2915 00004748 EBEC                <1> 	jmp	short sysexec_11
  2916                              <1> 	;
  2917                              <1> 	; 1:
  2918                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2919                              <1> 			     ; / pointers to arguments to be passed
  2920                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2921                              <1> 			      ; / u.quit = 1 take quit
  2922                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2923                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2924                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2925                              <1> 			       ; / system routine
  2926                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector
  2927                              <1> 			       ; / set to take system routine
  2928                              <1> 		; mov $sstack,sp / stack space used during swapping
  2929                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2930                              <1> 		; mov $ecore,r5 / r5 has end of core
  2931                              <1> 		; mov $core,r4 / r4 has start of users core
  2932                              <1> 		; mov r4,u.base / u.base has start of users core
  2933                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2934                              <1> 	; 1:
  2935                              <1> 		; tst (r2)+ / argument char = "nul"
  2936                              <1> 		; bne 1b
  2937                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of
  2938                              <1> 			  ; / end of argument pointer list
  2939                              <1> 	; 1:
  2940                              <1> 	     ; / move arguments to bottom of users core
  2941                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2942                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2943                              <1> 			    ; / ptr list
  2944                              <1> 		; blo 1f / branch to 1f when all arguments
  2945                              <1> 		       ; / are moved
  2946                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2947                              <1> 	; 2:
  2948                              <1> 		; tstb (r3)+
  2949                              <1> 		; bne 2b / scan argument for \0 (nul)
  2950                              <1> 
  2951                              <1> 	; 2:
  2952                              <1> 		; movb -(r3),-(r5) / move argument char 
  2953                              <1> 				 ; / by char starting at "ecore"
  2954                              <1> 		; cmp r3,(r2) / moved all characters in 
  2955                              <1> 			    ; / this argument
  2956                              <1> 		; bhi 2b / branch 2b if not
  2957                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2958                              <1> 			     ; / r5 has pointer to nth arg
  2959                              <1> 		; br 1b / string
  2960                              <1> 	; 1:
  2961                              <1> 		; clrb -(r5)
  2962                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2963                              <1> 			; / last word of argument strings
  2964                              <1> 		; mov $core,r2
  2965                              <1> 	
  2966                              <1> 	; 1: / move argument pointers into core following 
  2967                              <1> 	      ; / argument strings
  2968                              <1> 		; cmp r2,r4
  2969                              <1> 		; bhis 1f / branch to 1f when all pointers
  2970                              <1> 			; / are moved
  2971                              <1> 		; mov (r2)+,-(r5)
  2972                              <1> 		; br 1b
  2973                              <1> 	; 1:
  2974                              <1> 		; sub $core,r4 / gives number of arguments *2
  2975                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2976                              <1> 		       ; / the number of args stored
  2977                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2978                              <1> 			     ; / of the argument pointers
  2979                              <1> sysexec_13:
  2980                              <1> 	; 30/11/2021
  2981                              <1> 	; 28/11/2021
  2982                              <1> 	; 19/10/2015
  2983                              <1> 	; 18/10/2015
  2984                              <1> 	; 29/07/2015
  2985                              <1> 	; 25/07/2015
  2986                              <1> 	; 24/07/2015
  2987                              <1> 	; 20/07/2015
  2988                              <1> 	; 25/06/2015
  2989                              <1> 	; 24/06/2015
  2990                              <1> 	; 23/06/2015
  2991                              <1> 	;
  2992                              <1> 	; moving arguments to [ecore] is OK here..
  2993                              <1> 	; 18/10/2015
  2994 0000474A 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2995                              <1> 	; ebx = beginning address of argument list pointers
  2996                              <1> 	;	in user's stack
  2997                              <1> 	; 19/10/2015
  2998 0000474C 2B1D[2C760000]      <1> 	sub 	ebx, [ecore]
  2999 00004752 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  3000                              <1> 			; end of core - 4096 (last page)
  3001                              <1> 			; (virtual address)
  3002 00004758 891D[3C760000]      <1> 	mov	[argv], ebx
  3003 0000475E 891D[DC750000]      <1> 	mov	[u.break], ebx ; available user memory
  3004                              <1> 	;
  3005 00004764 29C0                <1> 	sub	eax, eax
  3006 00004766 C705[D4750000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  3006 0000476E 0000                <1>
  3007                              <1> 		; mov $14,u.count
  3008 00004770 C705[C0750000]-     <1> 	mov	dword [u.fofp], u.off
  3008 00004776 [CC750000]          <1>
  3009                              <1> 		; mov $u.off,u.fofp
  3010 0000477A A3[CC750000]        <1> 	mov	[u.off], eax ; 0
  3011                              <1> 		; clr u.off / set offset in file to be read to zero
  3012                              <1> 	; 25/07/2015
  3013 0000477F A3[D0750000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  3014                              <1> 	; 25/06/2015 
  3015 00004784 A1[88750000]        <1> 	mov	eax, [ii] ; 28/11/2021 (32 bit inode number)
  3016                              <1> 	; AX = i-number of the executable file
  3017 00004789 E8F3100000          <1> 	call	readi
  3018                              <1> 		; jsr r0,readi / read in first six words of 
  3019                              <1> 			; / user's file, starting at $core
  3020                              <1> 		; mov sp,r5 / put users stack address in r5
  3021                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  3022                              <1> 				; / from r5 (leaves number of words
  3023                              <1> 				; / less 26 available for
  3024                              <1> 			     	; / program in user core
  3025                              <1> 		; mov r5,u.count /
  3026                              <1> 	; 25/06/2015
  3027 0000478E 8B0D[DC750000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  3028 00004794 890D[D4750000]      <1> 	mov	[u.count], ecx ; save for overrun check
  3029                              <1> 	;
  3030 0000479A 8B0D[D8750000]      <1> 	mov	ecx, [u.nread]
  3031 000047A0 890D[DC750000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  3032 000047A6 80F920              <1> 	cmp	cl, 32
  3033 000047A9 7540                <1>         jne     short sysexec_15
  3034                              <1> 	;:
  3035                              <1> 	; 25/06/2015
  3036                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  3037                              <1> 	; 18/10/2015
  3038 000047AB 8B35[28760000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  3039                              <1> 		             ; (phys. start addr. of the exec. file)
  3040 000047B1 AD                  <1> 	lodsd
  3041 000047B2 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  3042 000047B6 7533                <1> 	jne	short sysexec_15
  3043                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  3044                              <1> 			      ; / if file is standard a.out format
  3045                              <1> 		; bne 1f / branch, if not standard format
  3046 000047B8 AD                  <1> 	lodsd
  3047 000047B9 89C1                <1> 	mov	ecx, eax ; text (code) section size
  3048 000047BB AD                  <1> 	lodsd
  3049 000047BC 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  3050                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  3051                              <1> 		              ; / number of bytes in program text
  3052                              <1> 		; sub $14,r5 / subtract 12
  3053 000047BE 89CB                <1> 	mov	ebx, ecx
  3054                              <1> 	;
  3055                              <1> 	; 25/06/2015
  3056                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  3057                              <1> 	;	and SINGLIX operating systems (as code template).
  3058                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  3059                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  3060                              <1> 	;	Overrun is not possible for current version.
  3061                              <1> 	;
  3062 000047C0 AD                  <1> 	lodsd	
  3063 000047C1 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  3064 000047C3 3B1D[D4750000]      <1> 	cmp	ebx, [u.count]
  3065 000047C9 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  3066                              <1> 	;
  3067                              <1> 	; 24/07/2015
  3068                              <1> 	; add bss section size to [u.break]
  3069 000047CB 0105[DC750000]      <1> 	add 	[u.break], eax
  3070                              <1> 	;
  3071 000047D1 83E920              <1> 	sub	ecx, 32 ; header size (already loaded)
  3072                              <1> 	;cmp	ecx, [u.count]
  3073                              <1> 	;jnb	short sysexec_16
  3074                              <1> 		; cmp r5,u.count /
  3075                              <1> 		; bgt 1f / branch if r5 greater than u.count
  3076 000047D4 890D[D4750000]      <1> 	mov	[u.count], ecx ; required read count
  3077                              <1> 		; mov r5,u.count
  3078                              <1> 	;
  3079 000047DA EB29                <1> 	jmp	short sysexec_16
  3080                              <1> 	;
  3081                              <1> sysexec_14:
  3082                              <1> 	; 23/06/2015
  3083                              <1> 	; insufficient (out of) memory
  3084 000047DC C705[20760000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  3084 000047E4 0000                <1>
  3085 000047E6 E95DF3FFFF          <1> 	jmp	error
  3086                              <1> 	;
  3087                              <1> sysexec_15:
  3088                              <1> 	; 25/06/2015
  3089                              <1>         ;movzx   edx, word [i.size] ; file size
  3090                              <1> 	; 30/11/2021
  3091 000047EB 8B15[60710000]      <1> 	mov	edx, [i.size] ; file size
  3092 000047F1 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  3093 000047F3 7626                <1> 	jna	short sysexec_17 ; no need to next read
  3094 000047F5 01D1                <1> 	add	ecx, edx ; [i.size]
  3095 000047F7 3B0D[D4750000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  3096 000047FD 77DD                <1> 	ja	short sysexec_14
  3097 000047FF 8915[D4750000]      <1> 	mov	[u.count], edx
  3098                              <1> sysexec_16:
  3099                              <1> 	;mov	ax, [ii] ; i-number
  3100                              <1> 	; 28/11/2021
  3101 00004805 A1[88750000]        <1> 	mov	eax, [ii] ; 32 bit inode number
  3102 0000480A E872100000          <1> 	call	readi
  3103                              <1> 		; add core+10,u.nread / add size of user data area
  3104                              <1> 		                    ; / to u.nread
  3105                              <1> 		; br 2f
  3106                              <1> 	; 1:
  3107                              <1> 		; jsr r0,readi / read in rest of file
  3108                              <1> 	; 2:
  3109 0000480F 8B0D[D8750000]      <1> 	mov	ecx, [u.nread]
  3110 00004815 010D[DC750000]      <1> 	add	[u.break], ecx
  3111                              <1> 		; mov u.nread,u.break / set users program break to end of
  3112                              <1> 				    ; / user code
  3113                              <1> 		; add $core+14,u.break / plus data area
  3114                              <1> 	; 20/07/2015
  3115                              <1> sysexec_17:
  3116                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  3117                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3118                              <1> 	;;mov	ax, [ii] ; i-number
  3119                              <1> 	;call	iclose
  3120                              <1> 	;	; jsr r0,iclose / does nothing
  3121 0000481B 31C0                <1>         xor     eax, eax
  3122 0000481D FEC0                <1> 	inc	al
  3123 0000481F 66A3[F8750000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3124 00004825 66A3[FA750000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3125                              <1> 	; 30/11/2021
  3126 0000482B FEC8                <1> 	dec	al  ; eax = 0
  3127                              <1> 	; 02/07/2015
  3128                              <1>         ;cmp	dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ?
  3129 0000482D 3905[10760000]      <1> 	cmp	[u.ppgdir], eax ; 0 ; is the caller sys_init (kernel) ?
  3130 00004833 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3131                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3132 00004835 8B15[98700000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3133 0000483B 8915[10760000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here
  3134                              <1> sysexec_18:
  3135                              <1> 	; 18/10/2015
  3136                              <1> 	; 05/08/2015
  3137                              <1> 	; 29/07/2015
  3138 00004841 8B2D[3C760000]      <1> 	mov	ebp, [argv] ; user's stack pointer must points to argument
  3139                              <1> 			    ; list pointers (argument count)
  3140 00004847 FA                  <1> 	cli
  3141 00004848 8B25[34700000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3142                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3143                              <1> 			    ; for this process	 
  3144                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3145                              <1> 	;;xor	eax, eax ; 0
  3146                              <1> 	;dec	al ; eax = 0
  3147                              <1> 	; eax = 0 ; 30/11/2021 
  3148 0000484E 66BA2300            <1> 	mov	dx, UDATA
  3149 00004852 6652                <1> 	push	dx  ; user's stack segment
  3150 00004854 55                  <1> 	push	ebp ; user's stack pointer
  3151                              <1> 		    ; (points to number of arguments)
  3152 00004855 FB                  <1> 	sti
  3153 00004856 9C                  <1> 	pushfd	; EFLAGS
  3154                              <1> 		; Set IF for enabling interrupts in user mode
  3155                              <1> 	;or	dword [esp], 200h 
  3156                              <1> 	;
  3157                              <1> 	;mov	bx, UCODE
  3158                              <1> 	;push	bx ; user's code segment
  3159 00004857 6A1B                <1> 	push	UCODE
  3160                              <1> 	;push	0
  3161 00004859 50                  <1> 	push	eax ; EIP (=0) - start address -
  3162                              <1> 		; clr -(r5) / popped into ps when rti in 
  3163                              <1> 			  ; / sysrele is executed
  3164                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3165                              <1> 		                ; / in sysrele is executed
  3166                              <1> 		;mov r5,0f / load second copyz argument
  3167                              <1> 		;tst -(r5) / decrement r5
  3168 0000485A 8925[A4750000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3169                              <1> 	; 05/08/2015
  3170                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3171                              <1> 	; ('push dx' would cause to general protection fault, 
  3172                              <1> 	; after 'pop ds' etc.)
  3173                              <1> 	;
  3174                              <1> 	;; push dx ; ds (UDATA)
  3175                              <1> 	;; push dx ; es (UDATA)
  3176                              <1> 	;; push dx ; fs (UDATA)
  3177                              <1> 	;; push dx ; gs (UDATA)
  3178                              <1> 	;
  3179                              <1> 	; This is a trick to prevent general protection fault
  3180                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3181 00004860 8EC2                <1> 	mov 	es, dx ; UDATA
  3182 00004862 06                  <1> 	push 	es ; ds (UDATA)
  3183 00004863 06                  <1> 	push 	es ; es (UDATA)
  3184 00004864 06                  <1> 	push 	es ; fs (UDATA)
  3185 00004865 06                  <1> 	push	es ; gs (UDATA)
  3186 00004866 66BA1000            <1> 	mov	dx, KDATA
  3187 0000486A 8EC2                <1> 	mov	es, dx
  3188                              <1> 	;
  3189                              <1> 	;; pushad simulation
  3190 0000486C 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3191 0000486E 50                  <1> 	push	eax ; eax (0)
  3192 0000486F 50                  <1> 	push	eax ; ecx (0)
  3193 00004870 50                  <1> 	push	eax ; edx (0)
  3194 00004871 50                  <1> 	push	eax ; ebx (0)
  3195 00004872 55                  <1> 	push	ebp ; esp before pushad
  3196 00004873 50                  <1> 	push	eax ; ebp (0)
  3197 00004874 50                  <1> 	push	eax ; esi (0)		
  3198 00004875 50                  <1> 	push	eax ; edi (0)	
  3199                              <1> 	;
  3200 00004876 A3[AC750000]        <1> 	mov	[u.r0], eax ; eax = 0
  3201 0000487B 8925[A8750000]      <1> 	mov	[u.usp], esp
  3202                              <1> 		; mov r5,u.r0 /
  3203                              <1> 		; sub $16.,r5 / skip 8 words
  3204                              <1> 		; mov r5,u.sp / assign user stack pointer value,
  3205                              <1> 		;             / effectively zeroes all regs
  3206                              <1> 			    ; / when sysrele is executed
  3207                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3208                              <1> 		; clr u.break
  3209                              <1> 		; mov r5,sp / point sp to user's stack
  3210                              <1> 	;
  3211 00004881 E9E4F2FFFF          <1> 	jmp	sysret0
  3212                              <1> 	;jmp	sysret
  3213                              <1> 		; br sysret3 / return to core image at $core
  3214                              <1> 
  3215                              <1> get_argp:
  3216                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  3217                              <1> 	; 18/10/2015 (nbase, ncount)
  3218                              <1> 	; 21/07/2015
  3219                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3220                              <1> 	; Get (virtual) address of argument from user's core memory
  3221                              <1> 	;
  3222                              <1> 	; INPUT:
  3223                              <1> 	;	esi = virtual address of argument pointer
  3224                              <1> 	; OUTPUT:
  3225                              <1> 	;	eax = virtual address of argument
  3226                              <1> 	;
  3227                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3228                              <1> 	;
  3229 00004886 833D[10760000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3230                              <1> 				    ; (the caller is kernel)
  3231 0000488D 767C                <1>         jna     short get_argpk 
  3232                              <1> 	;
  3233 0000488F 89F3                <1>      	mov	ebx, esi
  3234 00004891 E80AE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3235 00004896 7254                <1>         jc	short get_argp_err ; 11/12/2021
  3236 00004898 A3[30760000]        <1> 	mov 	[nbase], eax ; physical address	
  3237                              <1> 	;mov	[ncount], cx ; remain byte count in page (1-4096)
  3238                              <1> 	; 11/12/2021
  3239 0000489D 890D[34760000]      <1> 	mov	[ncount], ecx
  3240 000048A3 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3241                              <1> 	;cmp	cx, ax ; 4
  3242                              <1> 	; 11/12/2021
  3243 000048A8 39C1                <1> 	cmp	ecx, eax ; 4
  3244 000048AA 734A                <1> 	jnb	short get_argp2
  3245 000048AC 89F3                <1> 	mov	ebx, esi
  3246 000048AE 01CB                <1> 	add	ebx, ecx
  3247 000048B0 E8EBE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3248 000048B5 7235                <1> 	jc	short get_argp_err
  3249                              <1> 	;push	esi
  3250 000048B7 89C6                <1> 	mov	esi, eax
  3251                              <1> 	;xchg	cx, [ncount]
  3252                              <1> 	; 11/12/2021
  3253 000048B9 870D[34760000]      <1> 	xchg	ecx, [ncount]
  3254 000048BF 8735[30760000]      <1> 	xchg	esi, [nbase]
  3255 000048C5 B504                <1> 	mov	ch, 4
  3256 000048C7 28CD                <1> 	sub	ch, cl
  3257                              <1> get_argp0:
  3258 000048C9 AC                  <1> 	lodsb
  3259                              <1> 	;push	ax
  3260                              <1> 	; 11/12/2021
  3261 000048CA 50                  <1> 	push	eax
  3262 000048CB FEC9                <1> 	dec	cl
  3263 000048CD 75FA                <1>         jnz     short get_argp0
  3264 000048CF 8B35[30760000]      <1> 	mov	esi, [nbase]
  3265                              <1> 	; 21/07/2015
  3266 000048D5 0FB6C5              <1> 	movzx	eax, ch
  3267 000048D8 0105[30760000]      <1> 	add	[nbase], eax
  3268                              <1> 	;sub	[ncount], ax
  3269                              <1> 	; 11/12/2021
  3270 000048DE 2905[34760000]      <1> 	sub	[ncount], eax
  3271                              <1> get_argp1:
  3272 000048E4 AC                  <1> 	lodsb
  3273 000048E5 FECD                <1> 	dec	ch
  3274 000048E7 743B                <1>         jz      short get_argp3
  3275                              <1>         ;push	ax
  3276                              <1> 	; 11/12/2021
  3277 000048E9 50                  <1> 	push	eax
  3278 000048EA EBF8                <1> 	jmp     short get_argp1
  3279                              <1> get_argp_err:
  3280 000048EC A3[20760000]        <1> 	mov	[u.error], eax
  3281 000048F1 E952F2FFFF          <1> 	jmp	error
  3282                              <1> get_argp2:
  3283                              <1> 	; 21/07/2015
  3284                              <1> 	;mov	eax, 4
  3285 000048F6 8B15[30760000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3286 000048FC 0105[30760000]      <1> 	add	[nbase], eax
  3287                              <1> 	;sub	[ncount], ax
  3288                              <1> 	; 11/12/2021
  3289 00004902 2905[34760000]      <1> 	sub	[ncount], eax
  3290                              <1> 	;
  3291 00004908 8B02                <1> 	mov	eax, [edx]
  3292 0000490A C3                  <1> 	retn
  3293                              <1> get_argpk:
  3294                              <1> 	; Argument is in kernel's memory space
  3295 0000490B 66C705[34760000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3295 00004913 10                  <1>
  3296 00004914 8935[30760000]      <1> 	mov	[nbase], esi
  3297 0000491A 8305[30760000]04    <1> 	add	dword [nbase], 4
  3298 00004921 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physical addr.
  3299 00004923 C3                  <1> 	retn
  3300                              <1> get_argp3:
  3301 00004924 B103                <1> 	mov	cl, 3
  3302                              <1> get_argp4:
  3303 00004926 C1E008              <1> 	shl	eax, 8
  3304                              <1> 	;pop	dx
  3305                              <1> 	; 11/12/2021
  3306 00004929 5A                  <1> 	pop	edx
  3307 0000492A 88D0                <1> 	mov 	al, dl
  3308 0000492C E2F8                <1>         loop    get_argp4
  3309                              <1> 	;pop	esi
  3310 0000492E C3                  <1> 	retn	
  3311                              <1> 
  3312                              <1> sysfstat:
  3313                              <1> 	; 06/02/2022 
  3314                              <1> 	; 08/01/2022
  3315                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3316                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3317                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3318                              <1> 	;
  3319                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3320                              <1> 	; on open files instead of files given by name. It puts the
  3321                              <1> 	; buffer address on the stack, gets the i-number and
  3322                              <1> 	; checks to see if the file is open for reading or writing.
  3323                              <1> 	; If the file is open for writing (i-number is negative)
  3324                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3325                              <1> 	; is made.	
  3326                              <1> 	;
  3327                              <1> 	; Calling sequence:
  3328                              <1> 	;	sysfstat; buf
  3329                              <1> 	; Arguments:
  3330                              <1> 	;	buf - buffer address
  3331                              <1> 	;
  3332                              <1> 	; Inputs: *u.r0 - file descriptor
  3333                              <1> 	; Outputs: buffer is loaded with file information
  3334                              <1> 	; ...............................................................
  3335                              <1> 	;				
  3336                              <1> 	; Retro UNIX 8086 v1 modification:
  3337                              <1> 	;       'sysfstat' system call has two arguments; so,
  3338                              <1> 	;	* 1st argument, file descriptor is in BX register
  3339                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3340                              <1> 
  3341                              <1> 	; / set status of open file
  3342                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3343 0000492F 51                  <1> 	push	ecx ; *
  3344                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3345                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3346                              <1> 		; jsr r0,getf / get the files i-number
  3347                              <1> 	; BX = file descriptor (file number)
  3348 00004930 E8ED000000          <1> 	call	getf1
  3349                              <1> 	; 06/02/2022
  3350 00004935 21C0                <1> 	and	eax, eax
  3351                              <1> 	;and	ax, ax ; i-number of the file
  3352                              <1> 		; tst	r1 / is it 0?
  3353                              <1> 	;jz	error
  3354                              <1> 		; beq error3 / yes, error
  3355                              <1> 	;jnz	short sysfstat1
  3356                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2 (runix v2 file system)
  3357 00004937 752C                <1> 	jnz	short sysstat1
  3358 00004939 C705[20760000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3358 00004941 0000                <1>
  3359 00004943 E900F2FFFF          <1> 	jmp	error
  3360                              <1> 	; 26/12/2021
  3361                              <1> ;sysfstat1:
  3362                              <1> 	;cmp	ah, 80h
  3363                              <1>         ;jb      short sysstat1
  3364                              <1> 	;	; bgt 1f / if i-number is negative (open for writing)
  3365                              <1> 	;neg	ax
  3366                              <1> 	;	; neg r1 / make it positive, then branch
  3367                              <1> 	; 08/01/2022
  3368                              <1> 	;jmp	short sysstat1
  3369                              <1> 		; br 1f / to 1f
  3370                              <1> sysstat:
  3371                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3372                              <1> 	; 18/10/2015
  3373                              <1> 	; 07/10/2015
  3374                              <1> 	; 02/09/2015
  3375                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3376                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3377                              <1> 	;
  3378                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3379                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3380                              <1> 	; long and information about the file placed in it.	
  3381                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3382                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3383                              <1> 	; is then loaded and the results are given in the UNIX
  3384                              <1> 	; Programmers Manual sysstat (II).	
  3385                              <1> 	;
  3386                              <1> 	; Calling sequence:
  3387                              <1> 	;	sysstat; name; buf
  3388                              <1> 	; Arguments:
  3389                              <1> 	;	name - points to the name of the file
  3390                              <1> 	;	buf - address of a 34 bytes buffer
  3391                              <1> 	; Inputs: -
  3392                              <1> 	; Outputs: buffer is loaded with file information
  3393                              <1> 	; ...............................................................
  3394                              <1> 	;				
  3395                              <1> 	; Retro UNIX 8086 v1 modification: 
  3396                              <1> 	;       'sysstat' system call has two arguments; so,
  3397                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3398                              <1> 	;	to get sysstat system call arguments from the user;
  3399                              <1> 	;	* 1st argument, name is pointed to by BX register
  3400                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3401                              <1> 	;
  3402                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3403                              <1> 	;	      arguments which were in these registers;
  3404                              <1> 	;	      but, it returns by putting the 1st argument
  3405                              <1> 	;	      in 'u.namep' and the 2nd argument
  3406                              <1> 	;	      on top of stack. (1st argument is offset of the
  3407                              <1> 	;	      file/path name in the user's program segment.)		 	
  3408                              <1> 	
  3409                              <1> 	; / ; name of file; buffer - get files status
  3410                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3411 00004948 891D[C8750000]      <1> 	mov	[u.namep], ebx
  3412 0000494E 51                  <1> 	push	ecx ; *
  3413 0000494F E804010000          <1> 	call	namei
  3414                              <1> 		; jsr r0,namei / get the i-number for the file
  3415                              <1> 	;jc	error
  3416                              <1> 		; br error3 / no such file, error
  3417 00004954 730F                <1> 	jnc	short sysstat1
  3418                              <1> 	; pop 	ecx
  3419                              <1> sysstat_err0:
  3420                              <1> 	; 'file not found !' error
  3421 00004956 C705[20760000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3421 0000495E 0000                <1>
  3422 00004960 E9E3F1FFFF          <1> 	jmp	error
  3423                              <1> 
  3424                              <1> sysstat1: ; 1:
  3425 00004965 E8AB0B0000          <1> 	call	iget
  3426                              <1> 		; jsr r0,iget / get the i-node into core
  3427                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3428                              <1> 	; 02/09/2015
  3429 0000496A 8F05[D0750000]      <1> 	pop	dword [u.base] ; *
  3430                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3431 00004970 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3432 00004975 730A                <1> 	jnc 	short sysstat2
  3433                              <1> sysstat_err1:
  3434 00004977 A3[20760000]        <1> 	mov	dword [u.error], eax ; error code
  3435 0000497C E9C7F1FFFF          <1> 	jmp	error
  3436                              <1> sysstat2:
  3437 00004981 A0[88750000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3438 00004986 AA                  <1> 	stosb
  3439 00004987 FF05[D0750000]      <1> 	inc 	dword [u.base]
  3440                              <1> 	;dec 	cx
  3441 0000498D 49                  <1> 	dec	ecx ; 26/12/2021
  3442 0000498E 7505                <1> 	jnz	short sysstat3
  3443 00004990 E835000000          <1> 	call	sysstat_gpa
  3444                              <1> 	;jc	short sysstat_err1
  3445                              <1> sysstat3:
  3446 00004995 A0[89750000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3447 0000499A AA                  <1> 	stosb
  3448                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3449 0000499B FF05[D0750000]      <1> 	inc 	dword [u.base]
  3450                              <1> 	;;dec 	word [u.pcount]
  3451                              <1> 	;dec	cx
  3452 000049A1 49                  <1> 	dec	ecx ; 26/12/2021
  3453 000049A2 7505                <1> 	jnz	short sysstat4
  3454 000049A4 E821000000          <1> 	call	sysstat_gpa
  3455                              <1> 	;jc	short sysstat_err1	
  3456                              <1> sysstat4:
  3457 000049A9 BE[58710000]        <1> 	mov	esi, inode
  3458                              <1> 		; mov $inode,r2 / r2 points to i-node
  3459                              <1> sysstat5: ; 1:
  3460 000049AE A4                  <1> 	movsb
  3461                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3462 000049AF FF05[D0750000]      <1> 	inc 	dword [u.base]
  3463                              <1> 	;;dec 	word [u.pcount]
  3464                              <1> 	;dec	cx
  3465 000049B5 49                  <1> 	dec	ecx ; 26/12/2021
  3466 000049B6 7505                <1> 	jnz	short sysstat6
  3467 000049B8 E80D000000          <1> 	call	sysstat_gpa
  3468                              <1> 	;jc	short sysstat_err1
  3469                              <1> sysstat6:
  3470                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2
  3471 000049BD 81FE[98710000]      <1> 	cmp	esi, inode + 64 ; Retro UNIX v2 inode		
  3472                              <1> 	;cmp	esi, inode + 32
  3473                              <1> 		; cmp r2,$inode+32 / done?
  3474 000049C3 75E9                <1> 	jne	short sysstat5
  3475                              <1> 		; bne 1b / no, go back
  3476 000049C5 E99EF1FFFF          <1> 	jmp	sysret
  3477                              <1> 		; br sysret3 / return through sysret
  3478                              <1> 	;
  3479                              <1> sysstat_gpa: ; get physical address of file status buffer
  3480                              <1> 	; 02/09/2015
  3481 000049CA 8B1D[D0750000]      <1> 	mov 	ebx, [u.base]
  3482                              <1> 	; 07/10/2015
  3483 000049D0 E8CBE7FFFF          <1> 	call	get_physical_addr ; get physical address
  3484                              <1> 	;jc	short sysstat_gpa1
  3485 000049D5 72A0                <1> 	jc	short sysstat_err1
  3486                              <1> 	; 18/10/2015
  3487 000049D7 89C7                <1> 	mov	edi, eax ; physical address
  3488                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3489                              <1> ;sysstat_gpa1:
  3490 000049D9 C3                  <1> 	retn
  3491                              <1> 
  3492                              <1> fclose:
  3493                              <1> 	; 12/03/2022
  3494                              <1> 	; 11/02/2022
  3495                              <1> 	; 08/01/2022
  3496                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3497                              <1> 	; 08/04/2021
  3498                              <1> 	; 04/04/2021
  3499                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3500                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3501                              <1> 	;            (32 bit offset pointer modification)
  3502                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3503                              <1> 	;
  3504                              <1> 	; Given the file descriptor (index to the u.fp list)
  3505                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3506                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3507                              <1> 	; u.fp list is cleared. If all the processes that opened
  3508                              <1> 	; that file close it, then fsp etry is freed and the file
  3509                              <1> 	; is closed. If not a return is taken. 
  3510                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3511                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3512                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3513                              <1> 	; a check is made to see if the file is special.	
  3514                              <1> 	;
  3515                              <1> 	; INPUTS ->
  3516                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3517                              <1> 	;    u.fp - list of entries in the fsp table
  3518                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3519                              <1> 	; OUTPUTS ->
  3520                              <1> 	;    r1 - contains the same file descriptor
  3521                              <1> 	;    r2 - contains i-number
  3522                              <1> 	;
  3523                              <1> 	; ((AX = R1))
  3524                              <1> 	; ((Modified registers: edx, ebx, ecx, esi, edi, ebp))
  3525                              <1> 	;
  3526                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3527                              <1> 	;              if i-number of the file is 0. (error)
  3528                              <1> 
  3529                              <1> 	; 08/04/2021
  3530                              <1> 	; INPUT:
  3531                              <1> 	;	eax = file descriptor
  3532                              <1> 	; OUTPUT:
  3533                              <1> 	;	cf = 0 -> eax = file descriptor
  3534                              <1> 	;	cf = 1 -> file not open ; 11/02/2022
  3535                              <1> 
  3536                              <1> 	; 18/08/2020
  3537                              <1> 	;movzx	edx, ax ; **
  3538 000049DA 89C3                <1> 	mov	ebx, eax
  3539                              <1> 
  3540                              <1> 	; 18/08/2020
  3541                              <1> _fclose:
  3542 000049DC 53                  <1> 	push	ebx ; ***  ; file descriptor (index to u.fp)
  3543                              <1> 
  3544                              <1> 	;push	ax ; ***
  3545                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3546                              <1> 			     ; / the index to u.fp list)
  3547                              <1> 	; ebx = file descriptor/number
  3548 000049DD E840000000          <1> 	call	getf
  3549                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3550                              <1> 			    ; / cdev has device =, u.fofp 
  3551                              <1> 			    ; / points to 3rd word of fsp entry
  3552                              <1> 	;cmp	eax, 1 ; 18/08/2020
  3553 000049E2 6683F801            <1> 	cmp	ax, 1 ; r1
  3554                              <1> 		; tst r1 / is i-number 0?
  3555 000049E6 7238                <1> 	jb	short fclose_2
  3556                              <1> 		; beq 1f / yes, i-node not active so return
  3557                              <1> 		; tst (r0)+ / no, jump over error return
  3558                              <1> 	
  3559                              <1> 	;mov	ebx, edx ; **
  3560                              <1>  	; 18/08/2020
  3561 000049E8 8B1C24              <1> 	mov	ebx, [esp]
  3562                              <1> 	;mov	edx, eax 
  3563                              <1> 	;;mov 	dx, ax ; *
  3564                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3565                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3566                              <1> 			    ; / which is index to u.fp ; **
  3567 000049EB C683[B6750000]00    <1> 	mov	byte [ebx+u.fp], 0
  3568                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3569 000049F2 8B1D[C0750000]      <1> 	mov	ebx, [u.fofp]
  3570                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3571                              <1> 
  3572                              <1> 	; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3573                              <1> 	; ebx = 5th word of fsp entry (64 bit file offset)
  3574                              <1> fclose_0:
  3575                              <1> 	; 08/01/2022
  3576 000049F8 FE4BFE              <1> 	dec	byte [ebx-2] ; 18/08/2020 - Retro UNIX 386 v2
  3577                              <1> 	;dec	byte [ebx+4] ; 18/06/2015
  3578                              <1> 		; decb 2(r1) / decrement the number of processes 
  3579                              <1> 			   ; / that have opened the file
  3580 000049FB 7923                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3581                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3582                              <1> 	;
  3583                              <1> 	;push	dx ; *
  3584                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3585                              <1> 	;;xor	ax, ax ; 0
  3586                              <1> 	;xor	eax, eax ; 18/08/2020
  3587                              <1> 		; clear 1st word of fsp entry
  3588                              <1> 	;mov	[ebx-8], ax ; 0 ; 18/08/2020
  3589                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3590 000049FD 66C743F80000        <1> 	mov	word [ebx-8], 0 ; clear 1st word of fsp entry ; i-number
  3591                              <1> 			; Note: 32 bit i-node number field is ready but
  3592                              <1> 			;	it is not used in current runix version.	
  3593                              <1> 
  3594                              <1> 	;;mov	[ebx-4], ax ; 0
  3595                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3596                              <1> 	;mov	al, [ebx+5] ; 18/06/2015
  3597                              <1> 	;	; tstb	3(r1) / has this file been deleted
  3598                              <1> 	;and	al, al
  3599                              <1> 	;jz	short fclose_1
  3600                              <1> 	;	; beq 2f / no, branch
  3601                              <1> 
  3602                              <1> 	;push	edx ; * ; 18/08/2020
  3603                              <1> 	;mov	eax, edx ; * ; 18/08/2020
  3604                              <1> 
  3605                              <1> 	;; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3606                              <1> 	;;test	byte [ebx-3], 80h ; open mode & status flags
  3607                              <1> 	; 04/04/2021 - Retro UNIX 386 v2 (new fsp structure)
  3608                              <1> 	;test	byte [ebx-4], 80h ; open mode & status flags 
  3609                              <1> 	;jz	short fclose_1	; deleted file flag (bit 7)
  3610                              <1> 
  3611                              <1> 	; 04/04/2021
  3612 00004A03 31D2                <1> 	xor	edx, edx
  3613                              <1> 	; 08/01/2022
  3614 00004A05 8A53FD              <1> 	mov	dl, [ebx-3] ; open mode & status flags
  3615 00004A08 F6C280              <1> 	test	dl, 80h	    ; deleted file flag (bit 7)
  3616 00004A0B 7409                <1> 	jz	short fclose_1 ; (not deleted -while open-)
  3617 00004A0D 52                  <1> 	push	edx
  3618                              <1> 	; 12/03/2022
  3619 00004A0E 50                  <1> 	push	eax ; inode number 
  3620                              <1> 
  3621                              <1> 	; deleted file !
  3622                              <1> 
  3623                              <1> 	;mov	ax, dx ; *
  3624                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3625                              <1> 	; AX = inode number
  3626 00004A0F E80F050000          <1> 	call	anyi
  3627                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3628                              <1> 			    ; / check if file appears in fsp again
  3629                              <1> 	; 12/03/2022
  3630 00004A14 58                  <1> 	pop	eax ; inode number
  3631                              <1> 	; 04/04/2021
  3632 00004A15 5A                  <1> 	pop	edx
  3633                              <1> 	; 11/02/2022
  3634                              <1> 	;(cpu will come here if anyi returns -without error-)
  3635                              <1> 	;; 08/04/2021
  3636                              <1> 	;jc	short fclose_3 ; error code in eax	
  3637                              <1> 	;; 18/08/2020
  3638                              <1> 	;;jmp	short fclose_2
  3639                              <1> 
  3640                              <1> 	; ax = inode number
  3641                              <1> fclose_1: ; 2:
  3642                              <1> 	; 04/04/2021
  3643 00004A16 80E201              <1> 	and	dl, 1
  3644 00004A19 FEC2                <1> 	inc	dl ; 0 -> 1 (open for read), 1 -> 2 (open for write)
  3645                              <1> 	
  3646                              <1> 	;pop	eax ; * ; 18/08/2020 
  3647                              <1> 	;;pop	ax ; *
  3648                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3649 00004A1B E8C7150000          <1> 	call	iclose ; close if it is special file 
  3650                              <1> 		; jsr r0,iclose / check to see if it is a special file
  3651                              <1> 	; 11/02/2022
  3652                              <1> 	;(cpu will come here if iclose returns -without error-)
  3653                              <1> 	;; 08/04/2021
  3654                              <1> 	;jnc	short fclose_2
  3655                              <1> ;fclose_3:
  3656                              <1> ;	pop	ebx ; ***  ; file descriptor
  3657                              <1> ;	; eax = error code
  3658                              <1> ;	retn
  3659                              <1> fclose_2: ; 1:
  3660 00004A20 58                  <1> 	pop	eax ; *** ; 18/08/2020
  3661                              <1> 	;pop	ax ; ***
  3662                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3663 00004A21 C3                  <1> 	retn
  3664                              <1> 		; rts r0
  3665                              <1> 
  3666                              <1> 	; 08/01/2022
  3667                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3668                              <1> getf:	; / get the device number and the i-number of an open file
  3669                              <1> 	; 13/05/2015
  3670                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3671                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3672                              <1> 
  3673                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3674                              <1> 	;
  3675                              <1> 	; 16/05/2021
  3676                              <1> 	; 27/03/2020 - Retro UNIX 386 v2 
  3677                              <1> 	;	(new open files -fsp- structure)
  3678                              <1> 	; 13/05/2015
  3679                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3680                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3681                              <1> 	
  3682                              <1> 	; INPUT: 
  3683                              <1> 	;    ;eax = file descriptor/number
  3684                              <1> 	;     ebx = file descriptor/number ; 18/08/2020 	
  3685                              <1> 	; OUTPUT:
  3686                              <1> 	;     bl = open mode & status flag ; 27/03/2020
  3687                              <1> 	;        (bit 0 open mode flag, 0 = read, 1 = write)  
  3688                              <1> 	;    eax = inode number (in AX)
  3689                              <1> 	;          If eax = 0 -> file not open
  3690                              <1> 	;   byte [cdev] = logical drive number (of inode in eax)
  3691                              <1> 	;	
  3692                              <1> 	; Modified registers: eax, ebx
  3693                              <1> 
  3694                              <1> 	; 16/05/2021 ('getf' procedure, unix v7 x86 'fio.c')
  3695                              <1> 	; /*
  3696                              <1> 	;  * Convert a user supplied
  3697                              <1> 	;  * file descriptor into a pointer
  3698                              <1> 	;  * to a file structure.
  3699                              <1> 	;  * Only task is to check range
  3700                              <1> 	;  * of the descriptor.
  3701                              <1> 	;  */
  3702                              <1> 	; struct file *
  3703                              <1> 	; getf(f)
  3704                              <1> 	;
  3705                              <1> 	; 18/08/2020
  3706                              <1> 	; 	ebx = file descriptor/number
  3707                              <1> 
  3708                              <1> 	; 16/05/2021
  3709                              <1> 	;NOFILE	equ 10 ; 08/01/2022
  3710                              <1> 
  3711                              <1> 	; 18/08/2020
  3712                              <1> 	;mov	ebx, eax
  3713                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3714                              <1> 
  3715                              <1> 	; ebx = file descriptor/number
  3716                              <1> 
  3717                              <1> 	; 18/08/2020
  3718 00004A22 29C0                <1> 	sub	eax, eax ; eax = 0
  3719                              <1>  
  3720 00004A24 83FB0A              <1> 	cmp	ebx, 10 ; cmp ebx, NOFILE ; 16/05/2021
  3721                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3722 00004A27 732E                <1>         jnb	short getf2 ; 13/05/2015
  3723                              <1> 	;jnb	error
  3724                              <1> 		; bhis error3 / u.fp is table of users open files,
  3725                              <1> 			    ; / index in fsp table
  3726                              <1> 	; 08/01/2022
  3727 00004A29 8A83[B6750000]      <1> 	mov	al, [ebx+u.fp]
  3728                              <1> 	;mov	bl, [ebx+u.fp]
  3729                              <1> 		; movb u.fp(r1),r1 / r1 contains number of entry 
  3730                              <1> 		                 ; / in fsp table
  3731 00004A2F 08C0                <1> 	or	al, al ; 08/01/2022
  3732                              <1> 	;or	bl, bl
  3733                              <1> 	;jnz	short getf3
  3734 00004A31 7424                <1> 	jz	short getf2 ; 18/08/2020
  3735                              <1> 	;;jz	short getf4
  3736                              <1> 		; beq 1f / if its zero return
  3737                              <1> ;getf2:
  3738                              <1> ;	; 'File not open !' error (ax=0)
  3739                              <1> ;	;sub	eax, eax ; 18/08/2020
  3740                              <1> ;	retn
  3741                              <1> ;getf3:	
  3742                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3743                              <1> 	;
  3744                              <1> 	; 'fsp' table (10 bytes/entry)
  3745                              <1> 	; bit 15				   bit 0
  3746                              <1> 	; ---|-------------------------------------------
  3747                              <1> 	; r/w|		i-number of open file
  3748                              <1> 	; ---|-------------------------------------------
  3749                              <1> 	;		   device number
  3750                              <1> 	; -----------------------------------------------
  3751                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3752                              <1> 	; -----------------------------------------------
  3753                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3754                              <1> 	; ----------------------|------------------------
  3755                              <1> 	;  flag that says file 	| number of processes
  3756                              <1> 	;   has been deleted	| that have file open 
  3757                              <1> 	; ----------------------|------------------------
  3758                              <1> 
  3759                              <1> 	; Retro UNIX 386 v2 modification ! (27/03/2020)
  3760                              <1> 
  3761                              <1> 	; bit 15 				    bit 0
  3762                              <1> 	; ----------------------------------------------- byte 0
  3763                              <1> 	;    	       i-number of open file           
  3764                              <1> 	; ----------------------------------------------- byte 2
  3765                              <1> 	;          high word of 32 bit i-number       
  3766                              <1> 	; ----------------------------------------------- byte 4
  3767                              <1> 	;    open mode & status  |   device number     
  3768                              <1> 	; ----------------------------------------------- byte 6
  3769                              <1> 	;       reserved byte    |    open count  
  3770                              <1> 	; ----------------------------------------------- byte 8
  3771                              <1> 	;   offset pointer, i.e., r/w pointer to file 
  3772                              <1> 	; ----------------------------------------------- byte 10
  3773                              <1> 	;     64 bit file offset pointer (bit 16-31)  
  3774                              <1> 	; ----------------------------------------------- byte 12
  3775                              <1> 	;     64 bit file offset pointer (bit 32-47)   
  3776                              <1> 	; ----------------------------------------------- byte 14
  3777                              <1> 	;     64 bit file offset pointer (bit 48-63)  
  3778                              <1> 	; ----------------------------------------------- byte 16
  3779                              <1> 	
  3780                              <1> 	; 11/05/2015 - Retro UNIX 386 v1
  3781                              <1> 	;mov	eax, 10
  3782                              <1> 
  3783                              <1> 	; 27/03/2020 - Retro UNIX 386 v2	
  3784                              <1> 	;mov	eax, opfls.size ; mov eax, 16
  3785                              <1> 	
  3786                              <1> 	;sub	eax, eax ; 18/08/2020 ; eax = 0
  3787                              <1> 
  3788                              <1> 	;mov	al, opfls.size  ; mov al, 16
  3789                              <1> 	;
  3790                              <1> 	;mul	bl
  3791                              <1> 	;;mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3792                              <1> 	;; 27/03/2020
  3793                              <1> 	;mov	ebx, fsp-(opfls.size-opfls.offset) ; fsp-8
  3794                              <1> 	
  3795                              <1> 	;add	ebx, eax
  3796                              <1> 		; asl r1
  3797                              <1> 		; asl r1 / multiply by 8 to get index into 
  3798                              <1> 		       ; / fsp table entry
  3799                              <1> 		; asl r1
  3800                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3801                              <1> 			      ; / in the fsp entry
  3802                              <1> 	; 08/01/2022
  3803 00004A33 88C3                <1> 	mov	bl, al
  3804                              <1> 	; 18/08/2020
  3805 00004A35 FECB                <1> 	dec	bl ; zero based fsp table entry number
  3806                              <1> 	;shl	bl, 4 ; * 16 ; opfls.size
  3807                              <1> 	; 08/01/2022
  3808 00004A37 C1E304              <1> 	shl	ebx, 4 ; * 16 ; opfls.size
  3809 00004A3A 81C3[50720000]      <1> 	add	ebx, fsp+8 ; opfls.offset	
  3810                              <1> 	; ebx = address of the file offset pointer 
  3811                              <1> 	;	(not file offset! not fsp entry address !)
  3812                              <1> 
  3813 00004A40 891D[C0750000]      <1> 	mov	[u.fofp], ebx
  3814                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3815                              <1> 			     ; / in fsp entry in u.fofp
  3816                              <1> 	; 18/08/2020
  3817 00004A46 8A43FD              <1> 	mov	al, [ebx-3]  ; open mode & status flags
  3818                              <1> 
  3819 00004A49 50                  <1> 	push	eax
  3820                              <1> 
  3821                              <1> 	;mov	ax, [ebx]
  3822                              <1> 	;;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3823                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3824                              <1> 			     ;;dev number is in 1 byte
  3825                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3826                              <1> 
  3827                              <1> 	; 18/08/2020
  3828 00004A4A 8A43FC              <1> 	mov	al, [ebx-4]  ; logical drive number
  3829                              <1> 
  3830 00004A4D A2[8D750000]        <1> 	mov	[cdev], al
  3831                              <1> 
  3832                              <1> 	;dec	ebx
  3833                              <1> 	;dec	ebx
  3834                              <1> 	; 18/08/2020
  3835 00004A52 668B43F8            <1> 	mov	ax, [ebx-8]
  3836                              <1> 		; mov -(r1),r1 / and the i-number r1
  3837                              <1> 
  3838 00004A56 5B                  <1> 	pop	ebx ; ebx = bl = open mode and status flag
  3839                              <1> 		; (bit 0 is open mode flag, 0 = read, 1 = write)
  3840                              <1> 	; eax = inode number (in ax)	
  3841                              <1> 
  3842                              <1> getf2:	; 18/08/2020
  3843                              <1> getf4:	; 1: ; 08/01/2022
  3844 00004A57 C3                  <1> 	retn
  3845                              <1> 		; rts r0
  3846                              <1> 
  3847                              <1> 	; 08/01/2022
  3848                              <1> 	; 19/12/2021
  3849                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3850                              <1> namei:
  3851                              <1> 	; 18/10/2021
  3852                              <1> 	; 12/06/2021
  3853                              <1> 	; 01/05/2021
  3854                              <1> 	; 26/03/2021
  3855                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  3856                              <1> 	; 04/12/2015 (14 byte file names)
  3857                              <1> 	; 18/10/2015 (nbase, ncount)
  3858                              <1> 	; 12/10/2015
  3859                              <1> 	; 21/08/2015
  3860                              <1> 	; 18/07/2015
  3861                              <1> 	; 02/07/2015
  3862                              <1> 	; 17/06/2015
  3863                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3864                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3865                              <1> 	;
  3866                              <1> 	; 'namei' takes a file path name and returns i-number of
  3867                              <1> 	; the file in the current directory or the root directory
  3868                              <1> 	; (if the first character of the pathname is '/').	
  3869                              <1> 	;
  3870                              <1> 	; INPUTS ->
  3871                              <1> 	;    u.namep - points to a file path name
  3872                              <1> 	;    u.cdir - i-number of users directory
  3873                              <1> 	;    u.cdev - device number on which user directory resides	
  3874                              <1> 	; OUTPUTS ->
  3875                              <1> 	;    r1 - i-number of file
  3876                              <1> 	;    cdev
  3877                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3878                              <1> 	;               occurs in the search for file path name.
  3879                              <1> 	;	        If no match u.dirp points to the end of 
  3880                              <1> 	;               the directory and r1 = i-number of the current
  3881                              <1> 	;	        directory.	
  3882                              <1> 	; ((AX = R1))
  3883                              <1> 	;
  3884                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3885                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3886                              <1> 	;
  3887                              <1> 
  3888                              <1> 	;mov	ax, [u.cdir]
  3889                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3890                              <1> 			      ; / in r1
  3891                              <1> 	; 01/05/2021
  3892 00004A58 A1[B0750000]        <1> 	mov	eax, [u.cdir]	
  3893 00004A5D 8A15[B4750000]      <1> 	mov	dl, [u.cdrv]
  3894 00004A63 8815[8D750000]      <1> 	mov	[cdev], dl
  3895                              <1> 	;mov	dx, [u.cdrv]
  3896                              <1> 	;mov	[cdev], dx	; NOTE: Retro UNIX 8086 v1 
  3897                              <1> 				; device/drive number is in 1 byte, 
  3898                              <1> 				; not in 1 word!
  3899                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3900                              <1> 				; / into cdev
  3901                              <1> 	; 12/10/2015
  3902                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3903                              <1>       	; convert virtual (pathname) addr to physical address
  3904 00004A69 E808010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3905                              <1> 		; esi = physical address of [u.namep]
  3906                              <1> 		; ecx = byte count in the page
  3907 00004A6E 803E2F              <1> 	cmp	byte [esi], '/'
  3908                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3909 00004A71 751C                <1> 	jne	short namei_1
  3910                              <1> 		; bne 1f
  3911 00004A73 FF05[C8750000]      <1> 	inc	dword [u.namep]
  3912                              <1> 		; inc u.namep / go to next char
  3913                              <1> 	;dec	cx ; remain byte count in the page
  3914 00004A79 49                  <1> 	dec	ecx ; 18/10/2021
  3915 00004A7A 7506                <1> 	jnz	short namei_0
  3916                              <1> 	; 12/10/2015
  3917 00004A7C E8F5000000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3918                              <1> 		; esi = physical address (page start + offset)
  3919                              <1> 		; ecx = byte count in the page
  3920 00004A81 4E                  <1> 	dec	esi
  3921                              <1> namei_0:
  3922 00004A82 46                  <1> 	inc 	esi  ; go to next char
  3923                              <1> 	;mov	ax, [rootdir] ; 09/07/2013
  3924                              <1> 	; 18/10/2021
  3925 00004A83 A1[94750000]        <1> 	mov	eax, [rootdir]
  3926                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3927 00004A88 C605[8D750000]00    <1> 	mov	byte [cdev], 0
  3928                              <1> 		; clr cdev / clear device number
  3929                              <1> namei_1: ; 1:
  3930 00004A8F F606FF              <1> 	test	byte [esi], 0FFh
  3931                              <1> 	;jz	short getf4
  3932                              <1> 	; 26/03/2021
  3933                              <1> 	;jz	short getf2 ; retn
  3934                              <1> 	;;jz	nig
  3935                              <1> 		; tstb *u.namep / is the character in file name a nul
  3936                              <1> 		; beq nig / yes, end of file name reached; 
  3937                              <1> 			; / branch to "nig"
  3938                              <1> 	; 19/12/2021
  3939                              <1> namei_9:
  3940                              <1> 	; 12/06/2021
  3941                              <1> 	;jnz	short namei_2
  3942                              <1> 	;retn
  3943                              <1> 	; 08/01/2022
  3944 00004A92 74C3                <1> 	jz	short getf4
  3945                              <1> namei_2: ; 1:
  3946                              <1> 	; 18/10/2015
  3947 00004A94 8935[30760000]      <1> 	mov 	[nbase], esi
  3948                              <1> 	;mov 	[ncount], cx
  3949                              <1> 	; 18/10/2021
  3950 00004A9A 890D[34760000]      <1> 	mov	[ncount], ecx
  3951                              <1> 	;
  3952                              <1> 	;;mov	dx, 2
  3953                              <1> 	;mov	dl, 2 ; user flag (read, non-owner)
  3954                              <1> 	; 25/03/2021
  3955                              <1> 	;mov	dx, 100h ; IREAD - read, owner 
  3956                              <1> 	; 18/10/2021
  3957 00004AA0 29D2                <1> 	sub	edx, edx
  3958 00004AA2 FEC6                <1> 	inc	dh ; dx = 100h ; IREAD - read, owner 
  3959 00004AA4 E8560B0000          <1> 	call	access
  3960                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3961                              <1> 	; 'access' will not return here if user has not "r" permission !
  3962                              <1> 
  3963                              <1> 	;test 	word [i.flgs], 4000h
  3964                              <1> 	;	; bit $40000,i.flgs / directory i-node?
  3965                              <1>         ;jz	short namei_err
  3966                              <1> 		; beq error3 / no, got an error
  3967                              <1> 	; 26/03/2021 
  3968                              <1> ;	mov	al, [i.flgs+1]
  3969                              <1> ;	;test	al, 80h ; IFREG ; 80h
  3970                              <1> ;	;jz	short namei_err ; not a regular file ! (device!?)
  3971                              <1> ;	;and	al, 40h ; IFDIR ; 40h
  3972                              <1> ;	;jz	short namei_err ; not a sub directory !
  3973                              <1> ;	shl	al, 1 ; 80h (IFREG flag) -> cf = 1
  3974                              <1> ;	jnc	short namei_err ; not a regular file ! (device!?)
  3975                              <1> ;	shl	al, 1 ; 80h (IFDIR flag) -> cf = 1
  3976                              <1> ;	jnc	short namei_err ; not a sub directory !
  3977                              <1> 
  3978                              <1> 	; 27/03/2021
  3979 00004AA9 E8F9000000          <1> 	call	chk_dir ; check for directory, jump to 'error' if not
  3980                              <1> 	; CPU will be here if the inode is a (valid) directory inode
  3981                              <1> 
  3982                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3983                              <1> 	;xor	eax, eax
  3984                              <1> 	;mov	[u.off], eax ; 0
  3985                              <1> 	; 01/05/2021 - Retro UNIX 386 v2 inode structure
  3986 00004AAE A1[60710000]        <1> 	mov	eax, [i.size]
  3987                              <1> 	;mov	ax, [i.size]
  3988 00004AB3 A3[C4750000]        <1> 	mov	[u.dirp], eax
  3989                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3990                              <1> 		; clr u.off / u.off is file offset used by user
  3991                              <1> 	; 18/10/2021
  3992 00004AB8 31C0                <1> 	xor	eax, eax
  3993                              <1> 	;mov	[u.off], eax ; 0
  3994 00004ABA BB[CC750000]        <1> 	mov	ebx, u.off
  3995 00004ABF 8903                <1> 	mov	[ebx], eax ; mov dword [u.off], 0
  3996                              <1> 	;
  3997 00004AC1 891D[C0750000]      <1> 	mov	[u.fofp], ebx ; u.off ; 18/10/2021
  3998                              <1> 	;mov	dword [u.fofp], u.off
  3999                              <1> 			; mov $u.off,u.fofp / u.fofp is a pointer to 
  4000                              <1> 				  ; / the offset portion of fsp entry
  4001                              <1> namei_3: ; 2:
  4002 00004AC7 C705[D0750000]-     <1> 	mov	dword [u.base], u.dirbuf
  4002 00004ACD [E4750000]          <1>
  4003                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  4004                              <1> 				    ; / copied from a directory
  4005 00004AD1 C705[D4750000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  4005 00004AD9 0000                <1>
  4006                              <1>  		; mov $10.,u.count / u.count is byte count 
  4007                              <1> 				 ; / for reads and writes
  4008                              <1> 	;mov 	ax, [ii]
  4009                              <1> 	; 18/10/2021
  4010 00004ADB A1[88750000]        <1> 	mov	eax, [ii] ; (32 bit inode number)
  4011                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  4012 00004AE0 FE05[1E760000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  4013 00004AE6 E8960D0000          <1>     	call	readi
  4014                              <1> 		; jsr r0,readi / read 10. bytes of file 
  4015                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  4016                              <1> 
  4017 00004AEB 8B0D[D8750000]      <1> 	mov 	ecx, [u.nread]
  4018 00004AF1 09C9                <1> 	or 	ecx, ecx
  4019                              <1> 		; tst u.nread
  4020 00004AF3 741A                <1> 	jz	short nib
  4021                              <1> 		; ble nib / gives error return
  4022                              <1> 	;
  4023                              <1> 	;mov 	bx, [u.dirbuf]
  4024                              <1> 	;and 	bx, bx       
  4025                              <1> 	; 18/10/2021
  4026 00004AF5 66F705[E4750000]FF- <1> 	test	word [u.dirbuf], 0FFFFh
  4026 00004AFD FF                  <1>
  4027                              <1> 		; tst u.dirbuf /
  4028 00004AFE 7513                <1> 	jnz	short namei_4
  4029                              <1> 		; bne 3f / branch when active directory entry 
  4030                              <1> 		       ; / (i-node word in entry non zero)
  4031 00004B00 A1[CC750000]        <1> 	mov	eax, [u.off]
  4032 00004B05 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  4033 00004B08 A3[C4750000]        <1> 	mov	[u.dirp], eax
  4034                              <1> 		; mov u.off,u.dirp
  4035                              <1> 		; sub $10.,u.dirp
  4036 00004B0D EBB8                <1> 	jmp	short namei_3
  4037                              <1> 		; br 2b
  4038                              <1> 
  4039                              <1> 	; 18/07/2013
  4040                              <1> nib: 
  4041 00004B0F 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  4042 00004B11 F9                  <1> 	stc
  4043                              <1> nig:
  4044 00004B12 C3                  <1> 	retn
  4045                              <1> 
  4046                              <1> 	; 27/03/2021
  4047                              <1> ;namei_err:
  4048                              <1> 	; 16/06/2015
  4049                              <1> ;	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  4050                              <1> ;	jmp	error
  4051                              <1> 
  4052                              <1> namei_4: ; 3:
  4053                              <1> 	; 18/10/2015
  4054                              <1> 	; 12/10/2015
  4055                              <1> 	; 21/08/2015
  4056                              <1> 	; 18/07/2015
  4057 00004B13 8B2D[C8750000]      <1> 	mov	ebp, [u.namep]
  4058                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  4059 00004B19 BF[E6750000]        <1> 	mov 	edi, u.dirbuf + 2
  4060                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  4061                              <1> 	; 18/10/2015
  4062 00004B1E 8B35[30760000]      <1> 	mov	esi, [nbase]
  4063                              <1> 	;mov	cx, [ncount]
  4064                              <1> 	;and	cx, cx
  4065                              <1> 	; 18/10/2021
  4066 00004B24 8B0D[34760000]      <1> 	mov	ecx, [ncount]
  4067 00004B2A 21C9                <1> 	and	ecx, ecx
  4068 00004B2C 7505                <1> 	jnz	short namei_5	
  4069                              <1> 	;
  4070 00004B2E E849000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4071                              <1> 		; esi = physical address (page start + offset)
  4072                              <1> 		; ecx = byte count in the page
  4073                              <1> namei_5: ; 3:
  4074 00004B33 45                  <1> 	inc	ebp ; 18/07/2015
  4075 00004B34 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  4076                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  4077 00004B35 08C0                <1> 	or 	al, al
  4078 00004B37 741C                <1> 	jz 	short namei_7
  4079                              <1> 		; beq 3f / if char is nul, then the last char in string
  4080                              <1> 			; / has been moved
  4081 00004B39 3C2F                <1> 	cmp	al, '/'
  4082                              <1> 		; cmp r4,$'/ / is char a </>
  4083 00004B3B 7418                <1> 	je 	short namei_7
  4084                              <1> 		; beq 3f	
  4085                              <1> 	; 12/10/2015
  4086                              <1> 	;dec	cx ; remain byte count in the page
  4087 00004B3D 49                  <1> 	dec	ecx ; 18/10/2021
  4088 00004B3E 7505                <1> 	jnz	short namei_6
  4089 00004B40 E837000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4090                              <1> 		; esi = physical address (page start + offset)
  4091                              <1> 		; ecx = byte count in the page
  4092                              <1> namei_6:
  4093 00004B45 81FF[F4750000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4094                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  4095                              <1> 				     ; / all 8 bytes of file name
  4096 00004B4B 74E6                <1> 	je	short namei_5
  4097                              <1> 		; beq 3b
  4098 00004B4D AE                  <1> 	scasb	
  4099                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  4100                              <1> 			      ; / char read from directory
  4101 00004B4E 74E3                <1> 	je 	short namei_5
  4102                              <1> 		; beq 3b / branch if chars match
  4103                              <1> namei_10:
  4104 00004B50 E972FFFFFF          <1>         jmp	namei_3 ; 2b
  4105                              <1> 		; br 2b / file names do not match go to next directory entry
  4106                              <1> namei_7: ; 3:
  4107 00004B55 81FF[F4750000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4108                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  4109 00004B5B 7405                <1> 	je	short namei_8
  4110                              <1> 		; beq 3f
  4111                              <1> 	;mov 	ah, [edi]
  4112                              <1> 	;;inc 	edi 
  4113                              <1> 	;and 	ah, ah
  4114                              <1> 	;	; tstb (r3)+ /
  4115                              <1>         ; 18/10/2021
  4116 00004B5D F607FF              <1> 	test	byte [edi], 0FFh
  4117                              <1> 	; 08/01/2021
  4118 00004B60 75EE                <1> 	jnz	short namei_10 
  4119                              <1> 	;jnz	namei_3
  4120                              <1> 		; bne 2b
  4121                              <1> namei_8: ; 3
  4122 00004B62 892D[C8750000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  4123                              <1> 		; mov r2,u.namep / u.namep points to char 
  4124                              <1> 			       ; / following a / or nul
  4125                              <1> 	;mov	bx, [u.dirbuf]
  4126                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  4127                              <1> 				; / entry to r1
  4128 00004B68 20C0                <1> 	and 	al, al
  4129                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  4130                              <1> 		      ;  / if r4 = </> then go to next directory
  4131                              <1> 	;mov	ax, bx
  4132                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  4133                              <1>         ; 18/10/2021 (16 bit inode number in 32 bit register)
  4134 00004B6A 0FB705[E4750000]    <1> 	movzx	eax, word [u.dirbuf] 
  4135                              <1> 	; 19/12/2021
  4136 00004B71 E91CFFFFFF          <1> 	jmp	namei_9 ; eax = inode number
  4137                              <1> ;	jnz	namei_2 
  4138                              <1> ;		; bne 1b
  4139                              <1> ;	; AX = i-number of the file
  4140                              <1> ;;;nig:
  4141                              <1> ;	retn
  4142                              <1> 		; tst (r0)+ / gives non-error return
  4143                              <1> ;;nib:
  4144                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  4145                              <1> 		       ; ax = 0 -> file not found 
  4146                              <1> ;;	stc	; 27/05/2013
  4147                              <1> ;;	retn
  4148                              <1> 		; rts r0
  4149                              <1> 
  4150                              <1> trans_addr_nmbp:
  4151                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4152                              <1> 	; 18/10/2015
  4153                              <1> 	; 12/10/2015
  4154 00004B76 8B2D[C8750000]      <1> 	mov 	ebp, [u.namep]
  4155                              <1> trans_addr_nm: 
  4156                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4157                              <1> 	; Convert virtual (pathname) address to physical address
  4158                              <1> 	; (Retro UNIX 386 v1 feature only !)
  4159                              <1> 	; 18/10/2015
  4160                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  4161                              <1> 	; 02/07/2015
  4162                              <1> 	; 17/06/2015
  4163                              <1> 	; 16/06/2015
  4164                              <1> 	;
  4165                              <1> 	; INPUTS: 
  4166                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  4167                              <1> 	;	[u.pgdir] = user's page directory
  4168                              <1> 	; OUTPUT:
  4169                              <1> 	;       esi = physical address of the pathname
  4170                              <1> 	;	ecx = remain byte count in the page
  4171                              <1> 	;
  4172                              <1> 	; (Modified registers: EBX, ECX, EDX, ESI) ; 18/10/2021
  4173                              <1> 	;
  4174                              <1> 
  4175                              <1> 	; 18/10/2021
  4176 00004B7C 29C9                <1> 	sub	ecx, ecx
  4177                              <1> 	;
  4178                              <1>         ;cmp	dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  4179 00004B7E 390D[10760000]      <1> 	cmp	[u.ppgdir], ecx ; 0 ; 18/10/2021
  4180 00004B84 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  4181                              <1> 				     ; it is already physical address
  4182 00004B86 50                  <1>    	push	eax	
  4183 00004B87 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  4184 00004B89 E812E6FFFF          <1>        	call	get_physical_addr ; get physical address
  4185 00004B8E 7204                <1> 	jc	short tr_addr_nm_err
  4186                              <1> 	; 18/10/2015
  4187                              <1> 	; eax = physical address 
  4188                              <1> 	; ecx = remain byte count in page (1-4096) ; 18/10/2021
  4189                              <1> 		; 12/10/2015 (cx = [u.pncount])
  4190 00004B90 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  4191 00004B92 58                  <1> 	pop	eax 
  4192 00004B93 C3                  <1> 	retn
  4193                              <1> 
  4194                              <1> tr_addr_nm_err:
  4195 00004B94 A3[20760000]        <1> 	mov	[u.error], eax
  4196                              <1> 	;pop 	eax
  4197 00004B99 E9AAEFFFFF          <1> 	jmp	error
  4198                              <1> 
  4199                              <1> trans_addr_nmk:
  4200                              <1> 	; 12/10/2015
  4201                              <1> 	; 02/07/2015
  4202 00004B9E 8B35[C8750000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  4203                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  4204                              <1> 	; 18/10/2021
  4205 00004BA4 B510                <1> 	mov	ch, PAGE_SIZE/256
  4206 00004BA6 C3                  <1> 	retn
  4207                              <1> 
  4208                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  4209                              <1> chk_dir:
  4210                              <1> 	; 12/06/2021
  4211                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  4212                              <1> 	; Check for directory inode
  4213                              <1> 
  4214 00004BA7 8A0D[59710000]      <1> 	mov	cl, [i.flgs+1]
  4215                              <1> 	;test	cl, 80h ; IFREG ; 80h
  4216                              <1> 	;jz	short chk_dir_err ; not a regular file ! (device!?)
  4217                              <1> 	;and	cl, 40h ; IFDIR ; 40h
  4218                              <1> 	;jz	short chk_dir_err ; not a sub directory !
  4219 00004BAD D0E1                <1> 	shl	cl, 1 ; 80h (IFREG flag) -> cf = 1
  4220 00004BAF 7305                <1> 	jnc	short chk_dir_err ; not a regular file ! (device!?)
  4221 00004BB1 D0E1                <1> 	shl	cl, 1 ; 40h (IFDIR flag) -> cf = 1
  4222 00004BB3 7301                <1> 	jnc	short chk_dir_err ; not a sub directory !
  4223                              <1> 	; 12/06/2021
  4224 00004BB5 C3                  <1> 	retn
  4225                              <1> chk_dir_err:
  4226 00004BB6 C705[20760000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4226 00004BBE 0000                <1>
  4227 00004BC0 E983EFFFFF          <1> 	jmp	error
  4228                              <1> 
  4229                              <1> 	; 06/02/2022
  4230                              <1> 	; 08/01/2022
  4231                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  4232                              <1> syschdir:
  4233                              <1> 	; / makes the directory specified in the argument
  4234                              <1> 	; / the current directory
  4235                              <1> 	;
  4236                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  4237                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4238                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  4239                              <1> 	;
  4240                              <1> 	; 'syschdir' makes the directory specified in its argument
  4241                              <1> 	; the current working directory.
  4242                              <1> 	;
  4243                              <1> 	; Calling sequence:
  4244                              <1> 	;	syschdir; name
  4245                              <1> 	; Arguments:
  4246                              <1> 	;	name - address of the path name of a directory
  4247                              <1> 	;	       terminated by nul byte.	
  4248                              <1> 	; Inputs: -
  4249                              <1> 	; Outputs: -
  4250                              <1> 	; ...............................................................
  4251                              <1> 	;				
  4252                              <1> 	; Retro UNIX 8086 v1 modification:
  4253                              <1> 	;	 The user/application program puts address of 
  4254                              <1> 	;	 the path name in BX register as 'syschdir' 
  4255                              <1> 	; 	 system call argument.
  4256                              <1> 
  4257 00004BC5 891D[C8750000]      <1> 	mov	[u.namep], ebx
  4258                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  4259 00004BCB E888FEFFFF          <1> 	call	namei
  4260                              <1> 		; jsr r0,namei / find its i-number
  4261                              <1> 	;jc	error
  4262                              <1> 		; br error3
  4263 00004BD0 730F                <1> 	jnc	short syschdir0
  4264                              <1> 	; 'directory not found !' error
  4265 00004BD2 C705[20760000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  4265 00004BDA 0000                <1>
  4266 00004BDC E967EFFFFF          <1> 	jmp	error
  4267                              <1> syschdir0:
  4268                              <1> 	; 08/01/2022
  4269 00004BE1 66BA0001            <1> 	mov	dx, 100h  ; read access ; IREAD (100h)
  4270 00004BE5 E8150A0000          <1> 	call	access
  4271                              <1> 		; jsr r0,access; 2 / get i-node into core
  4272                              <1> 	
  4273                              <1> 	; 06/02/2022
  4274                              <1> 	;; 01/01/2022 (runix v2 fs inode flag)
  4275                              <1> 	;test	byte [i.flgs+1], 80h ; regular file ?
  4276                              <1> 	;jz	short syschdir2 ; no, error!
  4277                              <1> 	;test	byte [i.flgs+1], 40h ; directory flag ?
  4278                              <1> 	;;test	word [i.flgs], 4000h
  4279                              <1> 	;	; bit $40000,i.flgs / is it a directory?
  4280                              <1> 	;;jz	error 
  4281                              <1> 	;	; beq error3 / no error
  4282                              <1> 	;jnz	short syschdir1
  4283                              <1> ;syschdir2:
  4284                              <1> 	;mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4285                              <1> 	;jmp	error
  4286                              <1> 
  4287                              <1> 	; 06/02/2022
  4288                              <1> 	; check for directory, jump to 'error' if not
  4289 00004BEA E8B8FFFFFF          <1> 	call	chk_dir
  4290                              <1> 	; (cpu will not return here
  4291                              <1> 	;  if the inode it is not a valid dir inode)
  4292                              <1> 
  4293                              <1> syschdir1:
  4294 00004BEF 66A3[B0750000]      <1> 	mov	[u.cdir], ax
  4295                              <1> 		; mov r1,u.cdir / move i-number to users 
  4296                              <1> 			      ; / current directory
  4297                              <1> 	;mov	ax, [cdev]
  4298                              <1> 	;mov	[u.cdrv], ax
  4299                              <1> 	; 08/01/2022
  4300 00004BF5 A0[8D750000]        <1> 	mov	al, [cdev]
  4301 00004BFA A2[B4750000]        <1> 	mov	[u.cdrv], al
  4302                              <1> 		; mov cdev,u.cdev / move its device to users 
  4303                              <1> 			        ; / current device
  4304 00004BFF E964EFFFFF          <1> 	jmp	sysret
  4305                              <1> 		; br sysret3
  4306                              <1> 
  4307                              <1> syschmod: ; < change mode of file >
  4308                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4309                              <1> 	; 01/05/2021
  4310                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4311                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4312                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4313                              <1> 	;
  4314                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4315                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4316                              <1> 	; changed to 'mode'.
  4317                              <1> 	;
  4318                              <1> 	; Calling sequence:
  4319                              <1> 	;	syschmod; name; mode
  4320                              <1> 	; Arguments:
  4321                              <1> 	;	name - address of the file name
  4322                              <1> 	;	       terminated by null byte.
  4323                              <1> 	;	mode - (new) mode/flags < attributes >
  4324                              <1> 	;	
  4325                              <1> 	; Inputs: -
  4326                              <1> 	; Outputs: -
  4327                              <1> 	; ...............................................................
  4328                              <1> 	;				
  4329                              <1> 	; Retro UNIX 8086 v1 modification: 
  4330                              <1> 	;       'syschmod' system call has two arguments; so,
  4331                              <1> 	;	* 1st argument, name is pointed to by BX register
  4332                              <1> 	;	* 2nd argument, mode is in CX register
  4333                              <1> 	;
  4334                              <1> 	; Mode bits (Flags):
  4335                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4336                              <1> 	;	bit 14 - directory flag (4000h)
  4337                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4338                              <1> 	;	bit 12 - large file flag (1000h)
  4339                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4340                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4341                              <1> 	;	bit 4 - executable flag (10h)
  4342                              <1> 	;	bit 3 - read permission for owner (08h)
  4343                              <1> 	;	bit 2 - write permission for owner (04h)
  4344                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4345                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4346                              <1> 
  4347                              <1> 	; 01/05/2021 (07/02/2020)
  4348                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  4349                              <1> 	; 	bit 15 - IFREG - regular file (8000h)
  4350                              <1> 	;	bit 14 - IFDIR - directory (4000h)
  4351                              <1> 	;	bit 13 - IRSVD - 0 - reserved/mounted bit (2000h)
  4352                              <1> 	; 	bit 12 - ILARG - large file addressing bit (1000h)
  4353                              <1> 	; 	bit 11 - ISUID - set user id on exec (800h)
  4354                              <1> 	;	bit 10 - ISGID - set group id on exec (400h)
  4355                              <1> 	; 	bit  9 - IEXTT - 0 - use extents (200h)
  4356                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4357                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4358                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4359                              <1> 	; 	bit  5 - read, group (20h)
  4360                              <1> 	; 	bit  4 - write, group (10h)
  4361                              <1> 	; 	bit  3 - execute, group (08h)
  4362                              <1> 	;	bit  2 - read, others (04h)
  4363                              <1> 	; 	bit  1 - write, others (02h)
  4364                              <1> 	; 	bit  0 - execute, others (01h)
  4365                              <1> 	;
  4366                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  4367                              <1> 	;	bit 15 - IFREG - 0 - device file (8000h)
  4368                              <1> 	; 	bit 14 - IFBLK - block device (4000h)
  4369                              <1> 	; 	bit 13 - IFCHR - 1 - character special (2000h)
  4370                              <1> 	;	bit 12 - IFIFO - fifo special (1000h)
  4371                              <1> 	; 	bit 11 - IPIPE - pipe special (800h)
  4372                              <1> 	;	bit 10 - IREDIR - redirected (400h)
  4373                              <1> 	;	bit  9 - IEXTR - external device driver (200h)
  4374                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4375                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4376                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4377                              <1> 	; 	bit  5 - read, group (20h)
  4378                              <1> 	; 	bit  4 - write, group (10h)
  4379                              <1> 	; 	bit  3 - execute, group (08h)
  4380                              <1> 	;	bit  2 - read, others (04h)
  4381                              <1> 	; 	bit  1 - write, others (02h)
  4382                              <1> 	; 	bit  0 - execute, others (01h)
  4383                              <1> 
  4384                              <1> 	; / name; mode
  4385 00004C04 E877000000          <1> 	call	isown
  4386                              <1> 		; jsr r0,isown / get the i-node and check user status
  4387                              <1> 
  4388                              <1> 	; 25/05/2020
  4389                              <1> 	; AL = new mode (return form 'isown', ecx -> eax)
  4390                              <1> 
  4391                              <1> 	;test	word [i.flgs], 4000h
  4392                              <1> 	;	; bit $40000,i.flgs / directory?
  4393                              <1> 	;jz	short syschmod1
  4394                              <1> 	;	; beq 2f / no
  4395                              <1> 	;; AL = (new) mode
  4396                              <1> 	;and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4397                              <1> 	;	; bic $60,r2 / su & ex / yes, clear set user id and 
  4398                              <1> 	;		   ; / executable modes
  4399                              <1> 
  4400                              <1> 	; 01/05/2021
  4401                              <1> 	; AX = new mode (9 bits for devices or 12 bits files)
  4402 00004C09 8A15[59710000]      <1> 	mov	dl, [i.flgs+1]
  4403                              <1> 	; 09/01/2022
  4404 00004C0F F6C280              <1> 	test	dl, 80h ; regular file
  4405 00004C12 7416                <1> 	jz	short syschmod1 ; device file
  4406 00004C14 F6C240              <1> 	test	dl, 40h ; directory
  4407 00004C17 7511                <1> 	jnz	short syschmod1
  4408                              <1> 	; regular file
  4409 00004C19 6625FF0D            <1> 	and	ax, 0DFFh ; clear bit 9, 12-15 (of new mode)
  4410                              <1> 	; clear bit 8,10,11 of current mode/flags
  4411 00004C1D 80E2F2              <1> 	and	dl, 0F2h ; and dl, 11110010b
  4412                              <1> syschmod0:
  4413 00004C20 08D4                <1> 	or	ah, dl
  4414 00004C22 66A3[58710000]      <1> 	mov	[i.flgs], ax	
  4415 00004C28 EB45                <1> 	jmp	short syschmod2
  4416                              <1> syschmod1: 
  4417                              <1> 	; device or directory	
  4418 00004C2A 6625B601            <1> 	and	ax, 1B6h ; clear bit 9-15 & bit 0,3,6 (EXEC bits)
  4419                              <1> 	; clear bit 8 (IREAD) of current mode/flags
  4420                              <1> 	;	 (dl contains flag bits 8-15)
  4421 00004C2E 80E2FE              <1> 	and	dl, ~1 ; and dl, 11111110b 
  4422 00004C31 EBED                <1> 	jmp	short syschmod0
  4423                              <1> 
  4424                              <1> ;syschmod1: ; 2:
  4425                              <1> 	;mov	[i.flgs], al	
  4426                              <1> 	;	; movb r2,i.flgs / move remaining mode to i.flgs
  4427                              <1> 
  4428                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4429                              <1> 	;mov	byte [imodx], 1 ; (flag means file data is same
  4430                              <1> 	;			;  but inode's itself has been modified)
  4431                              <1> 	;call	setimod
  4432                              <1> 	;jmp	sysret
  4433                              <1> 
  4434                              <1> 	; 25/05/2020
  4435                              <1> 	;jmp	short syschmod2
  4436                              <1> 
  4437                              <1> syschown: ; < change owner of file >
  4438                              <1> 	; 13/03/2022
  4439                              <1> 	; 11/03/2022
  4440                              <1> 	; 14/02/2022
  4441                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4442                              <1> 	; 01/05/2021
  4443                              <1> 	;	(change owner and group ID of file)
  4444                              <1> 	; 02/04/2021
  4445                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4446                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4447                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4448                              <1> 	;
  4449                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4450                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4451                              <1> 	; changed to 'owner'
  4452                              <1> 	;
  4453                              <1> 	; Calling sequence:
  4454                              <1> 	;	syschown; name; owner
  4455                              <1> 	; Arguments:
  4456                              <1> 	;	name - address of the file name
  4457                              <1> 	;	       terminated by null byte.
  4458                              <1> 	;	owner - (new) owner (number/ID)
  4459                              <1> 	;	
  4460                              <1> 	; Inputs: -
  4461                              <1> 	; Outputs: -
  4462                              <1> 	; ...............................................................
  4463                              <1> 	;				
  4464                              <1> 	; Retro UNIX 8086 v1 modification: 
  4465                              <1> 	;       'syschown' system call has two arguments; so,
  4466                              <1> 	;	* 1st argument, name is pointed to by BX register
  4467                              <1> 	;	* 2nd argument, owner number is in CX register
  4468                              <1> 	;
  4469                              <1> 	; / name; owner
  4470 00004C33 E848000000          <1> 	call	isown
  4471                              <1> 		; jsr r0,isown / get the i-node and check user status
  4472                              <1> 	
  4473                              <1> 	; 25/05/2020
  4474                              <1> 	; AL = owner number (return form 'isown', ecx -> eax)
  4475                              <1> 	; 02/04/2021
  4476                              <1> 	; AX = owner number
  4477                              <1> 	; 01/05/2021
  4478                              <1> 	; byte 2 of EAX is group number
  4479                              <1> 
  4480                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013 
  4481                              <1> 	;	; tstb u.uid / super user
  4482                              <1> 	;jz	short syschown1
  4483                              <1> 	;	; beq 2f / yes, 2f
  4484 00004C38 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0
  4485 00004C40 741F                <1> 	jz	short syschown1
  4486                              <1> 
  4487                              <1> 	;test	byte [i.flgs], 20h ; 32
  4488                              <1> 	;	; bit $40,i.flgs / no, set userid on execution?
  4489                              <1> 	;;jnz	error
  4490                              <1> 	;	; bne 3f / yes error, could create Trojan Horses
  4491                              <1> 	;jz	short syschown1
  4492                              <1> 	; 01/05/2021
  4493                              <1> 	; check set user id on execution flag
  4494                              <1> 	; (protection against Trojan Horses)
  4495                              <1> 
  4496                              <1> 	; ((Note: UNIX v7 x86 'chown' source code in 'sys4.c'
  4497                              <1> 	;        does not contain this protection)) 
  4498                              <1> 
  4499                              <1> 	; 14/02/2022
  4500 00004C42 8A15[59710000]      <1> 	mov	dl, [i.flgs+1]
  4501 00004C48 F6C280              <1> 	test	dl, 80h ; IFREG ; RUNIX v2 inode flags  	
  4502 00004C4B 7405                <1> 	jz	short syschown_err ; device file !
  4503                              <1> 	; 09/01/2022
  4504                              <1> 	;test	byte [i.flgs+1], 08h ; ISUID ; RUNIX v2 inode flags  	
  4505                              <1> 	; 14/02/2022
  4506 00004C4D F6C208              <1> 	test	dl, 08h	; set user id on execution
  4507 00004C50 740F                <1> 	jz	short syschown1 ; 11/03/2022
  4508                              <1> 		; 11/03/2022
  4509                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4510                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4511                              <1> syschown_err:
  4512                              <1> 	; 'permission denied !'
  4513 00004C52 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4513 00004C5A 0000                <1>
  4514 00004C5C E9E7EEFFFF          <1> 	jmp	error
  4515                              <1> syschown1: ; 2:
  4516                              <1> 	;; AL = owner (number/ID)
  4517                              <1> 	;mov	[i.uid], al ; 23/06/2015
  4518                              <1> 	;	; movb r2,i.uid / no, put the new owners id 
  4519                              <1> 	;		      ; / in the i-node
  4520                              <1> 	; 02/04/2021 (Retro UNIX 386 v2)
  4521                              <1> 	; AX = owner number
  4522 00004C61 66A3[5C710000]      <1> 	mov	[i.uid], ax ; owner
  4523                              <1> 	; 13/03/2022
  4524                              <1> 	;; 14/02/2022 (Retro UNIX 386 v1.2)
  4525                              <1> 	;test	dl, 04h ; ISGID ; set grup id on execution
  4526                              <1> 	;jz	short syschown2
  4527                              <1> 	; 01/05/2021 (Retro UNIX 386 v2)
  4528 00004C67 C1E810              <1> 	shr	eax, 16
  4529 00004C6A A2[5E710000]        <1> 	mov	[i.gid], al ; group
  4530                              <1> syschown2:
  4531                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4532                              <1> syschmod2:
  4533                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4534 00004C6F C605[9F750000]01    <1> 	mov	byte [imodx], 1	; (flag means file data is same
  4535                              <1> 			      ;  but inode's itself has been modified)
  4536 00004C76 E82B0A0000          <1> 	call	setimod ; 25/05/2020
  4537                              <1> 	
  4538 00004C7B E9E8EEFFFF          <1> 	jmp	sysret
  4539                              <1> 
  4540                              <1> 	; 1: 
  4541                              <1> 		; jmp sysret4
  4542                              <1> 	; 3:
  4543                              <1> 		; jmp	error
  4544                              <1> 
  4545                              <1> isown:
  4546                              <1> 	; 11/03/2022
  4547                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4548                              <1> 	; 06/11/2021
  4549                              <1> 	; 12/06/2021
  4550                              <1> 	; 01/05/2021
  4551                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4552                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4553                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4554                              <1> 	;
  4555                              <1> 	; 'isown' is given a file name (the 1st argument).
  4556                              <1> 	;  It find the i-number of that file via 'namei' 
  4557                              <1> 	;  then gets the i-node into core via 'iget'.
  4558                              <1> 	;  It then tests to see if the user is super user. 
  4559                              <1> 	;  If not, it checks to see if the user is owner of 
  4560                              <1> 	;  the file. If he is not an error occurs.
  4561                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4562                              <1> 	;  the inode has been modified and the 2nd argument of
  4563                              <1> 	;  the call is put in r2.
  4564                              <1> 	;
  4565                              <1> 	; INPUTS ->
  4566                              <1> 	;    arguments of syschmod and syschown calls
  4567                              <1> 	; OUTPUTS ->
  4568                              <1> 	;    u.uid - id of user
  4569                              <1> 	;    imod - set to a 1
  4570                              <1> 	;    r2 - contains second argument of the system call
  4571                              <1> 	;
  4572                              <1> 	;   ((AX=R2) output as 2nd argument)
  4573                              <1> 	;
  4574                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))
  4575                              <1> 	;
  4576                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4577                              <1> 	;; ! 2nd argument on top of stack !
  4578                              <1> 	;; 22/06/2015 - 32 bit modifications
  4579                              <1> 	;; 07/07/2013
  4580 00004C80 891D[C8750000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4581 00004C86 51                  <1> 	push 	ecx ;* ; 2nd argument
  4582                              <1> 	;;
  4583 00004C87 E8CCFDFFFF          <1> 	call	namei
  4584                              <1> 		; jsr r0,namei / get its i-number
  4585                              <1>        ; Retro UNIX 8086 v1 modification !
  4586                              <1>        ; ax = 0 -> file not found 
  4587                              <1> 	;and	ax, ax
  4588                              <1> 	;jz	error
  4589                              <1> 	;jc	error ; 27/05/2013
  4590                              <1> 		; br error3
  4591 00004C8C 730F                <1> 	jnc	short isown1  ; 25/05/2020 (isown0 -> isown1)
  4592                              <1> 	; 'file not found !' error
  4593 00004C8E C705[20760000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4593 00004C96 0000                <1>
  4594 00004C98 E9ABEEFFFF          <1> 	jmp	error
  4595                              <1> isown1:
  4596 00004C9D E873080000          <1> 	call	iget
  4597                              <1> 		; jsr r0,iget / get i-node into core
  4598                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  4599                              <1> 	;; 06/11/2021
  4600                              <1> 	;jnc	short isown3
  4601                              <1> 	;mov	[u.error], eax
  4602                              <1> 	;jmp	error
  4603                              <1> ;isown3:
  4604                              <1> 	; check if it is super user ID
  4605                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4606 00004CA2 66A1[FE750000]      <1> 	mov	ax, [u.uid]
  4607 00004CA8 6609C0              <1> 	or	ax, ax
  4608                              <1> 	;mov	al, [u.uid] ; 02/08/2013
  4609                              <1> 	;or	al, al
  4610                              <1> 		; tstb u.uid / super user?
  4611                              <1> 	; 12/06/2021
  4612 00004CAB 7418                <1> 	jz	short isown2 ; 25/05/2020 (isown1 -> isown2)
  4613                              <1> 		; beq 1f / yes, branch
  4614                              <1> 	
  4615                              <1> 	; check user ID	(if same with file's owner)
  4616 00004CAD 663B05[5C710000]    <1> 	cmp	ax, [i.uid] ; 09/01/2022
  4617                              <1> 	;cmp	al, [i.uid]
  4618                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4619                              <1> 				 ; / the file
  4620                              <1> 	;jne	error
  4621                              <1> 		; beq 1f / yes
  4622                              <1> 		; jmp error3 / no, error
  4623                              <1> 	; 11/03/2022
  4624 00004CB4 740F                <1> 	je	short isown2 ; 25/05/2020
  4625                              <1> 	;; 01/05/2021
  4626                              <1> 	;jne	short isown_err
  4627                              <1> 
  4628                              <1> 	; 11/03/2022 (*)
  4629                              <1> 	; Note: It is seen as original unix (v5-v7) kernel
  4630                              <1> 	;	source handles 'u.gid' for group permissions
  4631                              <1> 	;	but kernel uses 'u.uid' as primary and unic
  4632                              <1> 	;	(singular) user id/number; a user group
  4633                              <1> 	;	does/can not contain same user id/number
  4634                              <1> 	;	with anotner group. So, if active/current
  4635                              <1> 	;	user ID is same with file's owner id,
  4636                              <1> 	;	group id check is not needed.
  4637                              <1> 	;	([u.uid] = [i.uid] is enough to confirm)	
  4638                              <1> 
  4639                              <1> 	; 01/05/2021
  4640                              <1> 	;mov	ax, [u.uid]
  4641                              <1> 	;or	ax, ax
  4642                              <1> 	;jz	short isown2 
  4643                              <1> 	;cmp	ax, [i.uid]
  4644                              <1> 	;;je	short isown2
  4645                              <1> 	;jne	short isown_err
  4646                              <1> 
  4647                              <1> 	; 01/05/2021
  4648                              <1> 	; ((Note: UNIX v7 x86 'chown', 'chmod' procedures
  4649                              <1> 	;    and their sub procedures do not check group ID))
  4650                              <1> 	; (('sys4.c', 'fio.c'))
  4651                              <1> 
  4652                              <1> 	; 11/03/2022 (*)
  4653                              <1> 	; 01/05/2021
  4654                              <1> 	; check group ID (if same with group of file's owner)
  4655                              <1> 	;mov	al, [u.gid]
  4656                              <1> 	;cmp	al, [i.gid]
  4657                              <1> 	;je	short isown2
  4658                              <1> isown_err:
  4659 00004CB6 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER ; 11
  4659 00004CBE 0000                <1>
  4660                              <1> 			; 'permission denied !' error
  4661 00004CC0 E983EEFFFF          <1> 	jmp	error
  4662                              <1> 
  4663                              <1> 	; 25/05/2020
  4664                              <1> ;isown2: ; 1:
  4665                              <1> ;	call	setimod
  4666                              <1> ;		; jsr r0,setimod / indicates 
  4667                              <1> ;		;	       ; / i-node has been modified
  4668                              <1> isown2: 
  4669                              <1> 	; 25/05/2020
  4670 00004CC5 58                  <1> 	pop	eax ;* ; 2nd argument
  4671                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4672                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4673 00004CC6 C3                  <1> 	retn
  4674                              <1> 
  4675                              <1> ;;arg:  ; < get system call arguments >
  4676                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4677                              <1> 	; of form:
  4678                              <1> 	;	sys 'routine' ; arg1
  4679                              <1> 	;		or
  4680                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4681                              <1> 	;		or
  4682                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4683                              <1> 	;	
  4684                              <1> 	; INPUTS ->
  4685                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4686                              <1> 	;	This pointers's value is actually the value of
  4687                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4688                              <1> 	;	made to process the sys instruction
  4689                              <1> 	;    r0 - contains the return address for the routine
  4690                              <1> 	;	that called arg. The data in the word pointer 
  4691                              <1> 	;	to by the return address is used as address
  4692                              <1> 	;	in which the extracted argument is stored
  4693                              <1> 	;    	
  4694                              <1> 	; OUTPUTS ->
  4695                              <1> 	;    'address' - contains the extracted argument 
  4696                              <1> 	;    u.sp+18 - is incremented by 2 
  4697                              <1> 	;    r1 - contains the extracted argument
  4698                              <1> 	;    r0 - points to the next instruction to be
  4699                              <1> 	;	 executed in the calling routine.
  4700                              <1> 	;
  4701                              <1>   
  4702                              <1> 	; mov u.sp,r1
  4703                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4704                              <1> 			; / into argument of arg2
  4705                              <1> 	; add $2,18.(r1) / point pc on stack 
  4706                              <1> 			      ; / to next system argument
  4707                              <1> 	; rts r0
  4708                              <1> 
  4709                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4710                              <1> 	; 'arg2' takes first argument in system call
  4711                              <1> 	;  (pointer to name of the file) and puts it in location
  4712                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4713                              <1> 	;  and on top of the stack
  4714                              <1> 	;	
  4715                              <1> 	; INPUTS ->
  4716                              <1> 	;    u.sp, r0
  4717                              <1> 	;    	
  4718                              <1> 	; OUTPUTS ->
  4719                              <1> 	;    u.namep
  4720                              <1> 	;    u.off 
  4721                              <1> 	;    u.off pushed on stack
  4722                              <1> 	;    r1
  4723                              <1> 	;
  4724                              <1> 
  4725                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4726                              <1> 				; / first arg in sys call
  4727                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4728                              <1> 				; / second arg in sys call
  4729                              <1> 	; mov r0,r1 / r0 points to calling routine
  4730                              <1> 	; mov (sp),r0 / put operation code back in r0
  4731                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4732                              <1> 			; / on stack
  4733                              <1> 	; jmp (r1) / return to calling routine
  4734                              <1> 
  4735                              <1> systime: ; / get time of year
  4736                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4737                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4738                              <1> 	;
  4739                              <1> 	; 20/06/2013
  4740                              <1> 	; 'systime' gets the time of the year.
  4741                              <1> 	; The present time is put on the stack.
  4742                              <1> 	;
  4743                              <1> 	; Calling sequence:
  4744                              <1> 	;	systime
  4745                              <1> 	; Arguments: -
  4746                              <1> 	;	
  4747                              <1> 	; Inputs: -
  4748                              <1> 	; Outputs: sp+2, sp+4 - present time
  4749                              <1> 	; ...............................................................
  4750                              <1> 	;	
  4751                              <1> 	; Retro UNIX 8086 v1 modification: 
  4752                              <1> 	;       'systime' system call will return to the user
  4753                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4754                              <1> 	;
  4755                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4756                              <1> 	;	system call for PC compatibility !!		 	
  4757                              <1> 
  4758 00004CC7 E847E9FFFF          <1> 	call 	epoch
  4759 00004CCC A3[AC750000]        <1> 	mov 	[u.r0], eax
  4760                              <1> 		; mov s.time,4(sp)
  4761                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4762                              <1> 				   ; / on the stack
  4763                              <1> 		; br sysret4
  4764 00004CD1 E992EEFFFF          <1> 	jmp	sysret 
  4765                              <1> 
  4766                              <1> sysstime: ; / set time
  4767                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4768                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4769                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4770                              <1> 	;
  4771                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4772                              <1> 	;
  4773                              <1> 	; Calling sequence:
  4774                              <1> 	;	sysstime
  4775                              <1> 	; Arguments: -
  4776                              <1> 	;	
  4777                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4778                              <1> 	; Outputs: -
  4779                              <1> 	; ...............................................................
  4780                              <1> 	;	
  4781                              <1> 	; Retro UNIX 8086 v1 modification: 
  4782                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4783                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4784                              <1> 	; 
  4785                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4786                              <1> 	;	to get sysstime system call arguments from the user;
  4787                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4788                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4789                              <1> 	;
  4790                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4791                              <1> 	;	system call for PC compatibility !!	
  4792                              <1> 
  4793                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4794 00004CD6 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0 ; 16 bit user ID
  4795                              <1> 	;cmp	byte [u.uid], 0
  4796                              <1> 		; tstb u.uid / is user the super user
  4797                              <1> 	;ja	error
  4798                              <1> 		; bne error4 / no, error
  4799 00004CDE 760F                <1> 	jna	short systime1
  4800                              <1> 	; 'permission denied !'
  4801 00004CE0 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4801 00004CE8 0000                <1>
  4802 00004CEA E959EEFFFF          <1> 	jmp	error
  4803                              <1> systime1:
  4804                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4805                              <1> 	; EBX = unix (epoch) time (from user)
  4806 00004CEF 89D8                <1> 	mov	eax, ebx
  4807 00004CF1 E89DEAFFFF          <1> 	call 	set_date_time
  4808                              <1> 		; mov 4(sp),s.time
  4809                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4810 00004CF6 E96DEEFFFF          <1> 	jmp	sysret
  4811                              <1> 		; br sysret4
  4812                              <1> 
  4813                              <1> sysbreak:
  4814                              <1> 	; 18/10/2015
  4815                              <1> 	; 07/10/2015
  4816                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4817                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4818                              <1> 	;
  4819                              <1> 	; 'sysbreak' sets the programs break points. 
  4820                              <1> 	; It checks the current break point (u.break) to see if it is
  4821                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4822                              <1> 	; even address (if it was odd) and the area between u.break
  4823                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4824                              <1> 	; in u.break and control is passed to 'sysret'.
  4825                              <1> 	;
  4826                              <1> 	; Calling sequence:
  4827                              <1> 	;	sysbreak; addr
  4828                              <1> 	; Arguments: -
  4829                              <1> 	;	
  4830                              <1> 	; Inputs: u.break - current breakpoint
  4831                              <1> 	; Outputs: u.break - new breakpoint 
  4832                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4833                              <1> 	; ...............................................................
  4834                              <1> 	;	
  4835                              <1> 	; Retro UNIX 8086 v1 modification:
  4836                              <1> 	;	The user/application program puts breakpoint address
  4837                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4838                              <1> 	; 	(argument transfer method 1)
  4839                              <1> 	;
  4840                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4841                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4842                              <1> 	;  NOTE:
  4843                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4844                              <1> 	;	'u.break' address) of user's memory for original unix's
  4845                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4846                              <1> 
  4847                              <1> 		; mov u.break,r1 / move users break point to r1
  4848                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4849                              <1> 		; blos 1f / yes, 1f
  4850                              <1> 	; 23/06/2015
  4851 00004CFB 8B2D[DC750000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4852                              <1> 	;and	ebp, ebp
  4853                              <1> 	;jz	short sysbreak_3 
  4854                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4855                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4856 00004D01 8B15[A4750000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4857 00004D07 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4858                              <1> 	; 07/10/2015
  4859 00004D0A 891D[DC750000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4860                              <1> 	;
  4861 00004D10 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4862                              <1> 			   ; with top of user's stack (virtual!)
  4863 00004D12 7327                <1> 	jnb	short sysbreak_3
  4864                              <1> 		; cmp r1,sp / is it the same or higher 
  4865                              <1> 			  ; / than the stack?
  4866                              <1> 		; bhis 1f / yes, 1f
  4867 00004D14 89DE                <1> 	mov	esi, ebx
  4868 00004D16 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4869 00004D18 7621                <1> 	jna	short sysbreak_3 
  4870                              <1> 	;push	ebx
  4871                              <1> sysbreak_1:
  4872 00004D1A 89EB                <1> 	mov	ebx, ebp  
  4873 00004D1C E87FE4FFFF          <1> 	call	get_physical_addr ; get physical address
  4874 00004D21 0F826DFEFFFF        <1> 	jc	tr_addr_nm_err
  4875                              <1> 	; 18/10/2015
  4876 00004D27 89C7                <1> 	mov	edi, eax 
  4877 00004D29 29C0                <1> 	sub	eax, eax ; 0
  4878                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4879 00004D2B 39CE                <1> 	cmp	esi, ecx
  4880 00004D2D 7302                <1> 	jnb	short sysbreak_2
  4881 00004D2F 89F1                <1> 	mov	ecx, esi
  4882                              <1> sysbreak_2:
  4883 00004D31 29CE                <1> 	sub	esi, ecx
  4884 00004D33 01CD                <1> 	add	ebp, ecx
  4885 00004D35 F3AA                <1> 	rep 	stosb
  4886 00004D37 09F6                <1> 	or	esi, esi
  4887 00004D39 75DF                <1> 	jnz	short sysbreak_1
  4888                              <1> 	;
  4889                              <1> 		; bit $1,r1 / is it an odd address
  4890                              <1> 		; beq 2f / no, its even
  4891                              <1> 		; clrb (r1)+ / yes, make it even
  4892                              <1> 	; 2: / clear area between the break point and the stack
  4893                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4894                              <1> 		; bhis 1f / yes, quit
  4895                              <1> 		; clr (r1)+ / clear word
  4896                              <1> 		; br 2b / go back
  4897                              <1> 	;pop	ebx
  4898                              <1> sysbreak_3: ; 1:
  4899                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4900                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4901                              <1> 			; / in u.break (set new break point)
  4902                              <1> 		; br sysret4 / br sysret
  4903 00004D3B E928EEFFFF          <1> 	jmp	sysret
  4904                              <1> 
  4905                              <1> maknod: 
  4906                              <1> 	; 12/03/2022
  4907                              <1> 	; 11/03/2022
  4908                              <1> 	; 14/02/2022
  4909                              <1> 	; 10/01/2022
  4910                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4911                              <1> 	; 06/11/2021 (Retro UNIX 386 v2)
  4912                              <1> 	; 15/08/2021
  4913                              <1> 	; 06/05/2021
  4914                              <1> 	; 02/05/2021
  4915                              <1> 	; 01/04/2021
  4916                              <1> 	; 27/03/2021
  4917                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  4918                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4919                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4920                              <1> 	;
  4921                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4922                              <1> 	; for this i-node in the current directory.
  4923                              <1> 	;
  4924                              <1> 	; INPUTS ->
  4925                              <1> 	;    r1 - contains mode
  4926                              <1> 	;    ii - current directory's i-number	
  4927                              <1> 	;    	
  4928                              <1> 	; OUTPUTS ->
  4929                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4930                              <1> 	;    i.flgs - flags in new i-node 
  4931                              <1> 	;    i.uid - filled with u.uid
  4932                              <1> 	;    i.nlks - 1 is put in the number of links
  4933                              <1> 	;    i.ctim - creation time
  4934                              <1> 	;    i.ctim+2 - modification time
  4935                              <1> 	;    imod - set via call to setimod
  4936                              <1> 	;	
  4937                              <1> 	; ((AX = R1)) input
  4938                              <1> 	;
  4939                              <1> 	; (Retro UNIX Prototype : 
  4940                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4941                              <1>         ; ((Modified registers: eax, edx, ebx, ecx, esi, edi, ebp))
  4942                              <1> 
  4943                              <1> 	; 27/03/2021
  4944                              <1> 	; INPUT:
  4945                              <1>  	;	AX = mode
  4946                              <1> 	;
  4947                              <1> 	; ('maknod' is called by 'syscreat' and 'sysmkdir')
  4948                              <1> 	; (('syscreat' and 'sysmkdir' will set AX input))
  4949                              <1> 
  4950                              <1> 	; 27/03/2021
  4951                              <1> 	; Retro UNIX 386 v2 inode mode flags (ref: 'ux.s')
  4952                              <1> 	; for File Inode: (high byte)
  4953                              <1> 	;   IFREG - 1 = regular file (8000h)
  4954                              <1> 	;   IFDIR - 1 = directory (4000h)
  4955                              <1> 	;   IRSVD - 0 = reserved bit (2000h) ; Mounted flag for dirs
  4956                              <1> 	;   ILARG - large file addressing bit (1000h)
  4957                              <1> 	;   ISUID - set user id on exec (800h)
  4958                              <1> 	;   ISGID - set group id on exec (400h)
  4959                              <1> 	;   IEXTT - 1 = use extents (200h)
  4960                              <1> 	;   IREAD - read, owner (100h)
  4961                              <1> 	; for Device Inode: (high byte)
  4962                              <1> 	;   IFREG - 0 = device file (8000h)
  4963                              <1> 	;   IFBLK - 1 = block device (4000h)
  4964                              <1> 	;   IFCHR - character special (2000h) -always 1-
  4965                              <1> 	;   IFIFO - fifo special (1000h)
  4966                              <1> 	;   IPIPE - pipe special (800h) ; 07/02/2020
  4967                              <1> 	;   IREDIR - redirected (400h)  ; 07/02/2020
  4968                              <1> 	;   IEXTR - 1 = external device driver (200h)
  4969                              <1> 	;   IREAD - read, owner (100h)
  4970                              <1> 
  4971                              <1> 	;; / r1 contains the mode
  4972                              <1> 	;or 	ah, 80h	; 10000000b
  4973                              <1> 	;	; bis $100000,r1 / allocate flag set
  4974                              <1> 
  4975                              <1> 	; 14/02/2022
  4976                              <1> 	; input ->
  4977                              <1> 	;   [u.namep] points to the file name address
  4978                              <1> 	;	     (in the user's memory space)
  4979                              <1> 	;   [u.dirp] points to empty slot in the directory
  4980                              <1> 
  4981                              <1> 	; high 3 bit will be checked here
  4982                              <1> 	; 	(ref: unix v7 x86 source, iget.c)
  4983                              <1> 
  4984                              <1> ;	; 27/03/2021
  4985                              <1> ;	test	ah, 0E0h ; 80h+40h+20h
  4986                              <1> ;	jnz	short maknod0	
  4987                              <1> ;
  4988                              <1> ;	; ('syscreat' clears ILARG & IEXTT bits)
  4989                              <1> ;	;and	ah, ~0Ch ; clear ILARG & IEXTT bits
  4990                              <1> ;	;	; user can set ISUID & ISGID bits
  4991                              <1> ;
  4992                              <1> ;	or	ah, 80h ; IFREG
  4993                              <1> ;maknod0:
  4994 00004D40 50                  <1> 	push	eax ; ***** ; 27/03/2021 (32 bit push, pop)
  4995                              <1> 		; mov r1,-(sp) / put mode on stack
  4996                              <1> 	; 31/07/2013
  4997                              <1> 	;mov	ax, [ii] ; move current i-number to AX/r1
  4998                              <1> 	;	; mov ii,r1 / move current i-number to r1
  4999                              <1> 	;mov	dl, 1 ; owner flag mask
  5000                              <1> 	; 15/08/2021
  5001                              <1> 	;movzx	eax, word [ii] ; move current i-number to EAX
  5002                              <1> 	; 09/01/2022
  5003 00004D41 A1[88750000]        <1> 	mov	eax, [ii] ; move current i-number to EAX
  5004                              <1> 	; 25/03/2021
  5005 00004D46 66BA8000            <1> 	mov	dx, 80h	; IWRITE - write,owner
  5006 00004D4A E8B0080000          <1> 	call	access	
  5007                              <1> 		; jsr r0,access; 1 / get its i-node into core
  5008                              <1> 	; 15/08/2021
  5009                              <1> 	; NOTE: cpu will not return here if there is a permission error
  5010                              <1> 	;	(it will jump to 'error' address from/in 'access')
  5011                              <1> 	
  5012 00004D4F 50                  <1> 	push	eax ; **** (parent) ; 27/03/2021 (32 bit push, pop)
  5013                              <1> 		; mov r1,-(sp) / put i-number on stack
  5014                              <1> 	;mov	ax, 40
  5015                              <1> 	;	; mov $40.,r1 / r1 = 40
  5016                              <1> 	; 27/03/2021
  5017 00004D50 31C0                <1> 	xor	eax, eax
  5018                              <1> 	;;dec	ax ; 0FFFFh
  5019                              <1> 	; 15/08/2021
  5020                              <1> 	;dec	eax ; 0FFFFFFFFh
  5021                              <1> 	; 01/04/2021
  5022                              <1> ;maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  5023                              <1> 	;;inc	ax
  5024                              <1> 	;	; inc r1 / r1 = r1 + 1
  5025                              <1> 	; 15/08/2021
  5026                              <1> 	;inc	eax
  5027                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5028                              <1> 	; eax = 0 -> start from first free inode
  5029                              <1> 	; eax > 0 -> locate this inode on the inode map buffer
  5030                              <1> 	; NOTE:
  5031                              <1> 	; Retro UNIX 386 v2 'imap' is mostly different than v1 'imap'
  5032                              <1> 	; ('imap' will not check inode table)
  5033 00004D52 E89D0A0000          <1> 	call	imap
  5034                              <1> 		; jsr r0,imap / get byte address and bit position in 
  5035                              <1> 			    ; /	inode map in r2 & m
  5036                              <1> 	; 09/01/2022
  5037                              <1> 	; (cpu will not return here if there would be an eror in imap)
  5038                              <1> 	; 15/08/2021
  5039                              <1> 	;jc	short maknod_err
  5040                              <1> 
  5041                              <1> 	; DX (MQ) has a 1 in the calculated bit position
  5042                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  5043                              <1> 
  5044                              <1> 	; 06/11/2021
  5045                              <1> 	; ebp = superblock buffer address
  5046                              <1> 	; eax = inode number
  5047                              <1> 	; 10/01/2022
  5048                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  5049                              <1> 	;		of current IMAP sector	
  5050                              <1> 
  5051                              <1> 	; 27/03/2021
  5052                              <1> 	; If cpu is here, there is not an error
  5053                              <1> 	; and EBX points to inode map buffer
  5054                              <1> 	; DL has 1 at bit position which is for free inode
  5055                              <1> 	; (E)AX = inode number
  5056                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  5057                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  5058                              <1> 
  5059                              <1> 	; 15/08/2021
  5060                              <1> maknod1:
  5061                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  5062                              <1> 	;	       Inode count must be checked here
  5063                              <1> 	; (Original UNIX v1 did not check inode count here !?)
  5064 00004D57 8413                <1> 	test	[ebx], dl
  5065                              <1> 		; bitb mq,(r2) / is the i-node active
  5066                              <1> 	;jnz	short maknod1
  5067                              <1> 	;	; bne 1b / yes, try the next one
  5068                              <1> 	; 15/08/2021
  5069 00004D59 7408                <1> 	jz	short maknod3 ; free inode (inactive inode)
  5070                              <1> maknod2:
  5071 00004D5B 40                  <1> 	inc	eax
  5072 00004D5C E8B70A0000          <1> 	call	imap_x ; next call to imap (bypass 1st call code)
  5073                              <1> 	; 10/01/2022
  5074                              <1> 	; (cpu will/would not return here 
  5075                              <1> 	;  if there is/was an error in 'imap_x')
  5076                              <1> 	;jnc	short maknod1
  5077 00004D61 EBF4                <1> 	jmp	short maknod1
  5078                              <1> 
  5079                              <1> 	; 14/02/2022
  5080                              <1> ;maknod_err:
  5081                              <1> ;	; 15/08/2021
  5082                              <1> ;	;pop	edx  ; two pops for stack alignment
  5083                              <1> ;	;pop	edx  ; (may not be needed while jumping to 'error')
  5084                              <1> ;	mov	[u.error], eax
  5085                              <1> ;	jmp	error
  5086                              <1> maknod3:
  5087                              <1> 	; 10/01/2022
  5088                              <1> 	; ebp = superblock buffer address
  5089                              <1> 	; eax = (free) inode number
  5090                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  5091                              <1> 	;			of current IMAP sector
  5092                              <1> 	; EBX = buffer address/offset for relevant alloc byte
  5093                              <1> 	;  DL has 1 at bit position which is for free inode
  5094                              <1> 	;
  5095                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  5096                              <1> 
  5097                              <1> 	;mov	[ebp+SB.LastInode], eax ; (free) inode number
  5098                              <1> 
  5099 00004D63 50                  <1> 	push	eax ; ***
  5100 00004D64 51                  <1> 	push	ecx ; **
  5101 00004D65 52                  <1> 	push	edx ; *
  5102 00004D66 55                  <1> 	push	ebp ; @ ; 11/03/2022
  5103                              <1> 
  5104 00004D67 8B457C              <1> 	mov	eax, [ebp+SB.ImapBuffer]
  5105                              <1> 
  5106 00004D6A E813150000          <1> 	call	wslot
  5107                              <1> 	; ebx = buffer data address (write operation bit is set)
  5108                              <1> 	; eax = physical sector number
  5109                              <1> 	; Note: ebx contains addr of the 1st buffer in the buf chain
  5110                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  5111 00004D6F 5D                  <1> 	pop	ebp ; @ ; 11/03/2022
  5112                              <1> 
  5113                              <1> 	;mov	[ebp+SB.ImapBuffer], ebx
  5114                              <1> 			; save inode map buffer address
  5115 00004D70 5A                  <1> 	pop	edx ; *
  5116 00004D71 59                  <1> 	pop	ecx ; **
  5117 00004D72 01CB                <1> 	add	ebx, ecx ; + byte offset (for allocation bit pos)	
  5118                              <1> 
  5119                              <1> 	; set allocation bit (for this new inode) ; 10/01/2022 
  5120 00004D74 0813                <1> 	or	[ebx], dl
  5121                              <1> 		; bisb mq,(r2) / no, make it active 
  5122                              <1> 			     ; / (put a 1 in the bit map)
  5123                              <1> 	;push	ebp ; @
  5124 00004D76 E823150000          <1> 	call	dskwr ; writes the 1st buffer to sector
  5125                              <1> 		      ; (at the beginning/head of the buffer chain)
  5126                              <1> 	;pop	ebp ; @
  5127                              <1> 
  5128                              <1> 	; if we are here, buffer has been written to disk successfully 
  5129                              <1> 	; (otherwise cpu would jump to 'error' address)
  5130                              <1> 
  5131                              <1> 	; set superblock modified flag
  5132 00004D7B BA[A0750000]        <1> 	mov	edx, smod
  5133 00004D80 F605[8D750000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  5134 00004D87 7401                <1> 	jz	short maknod4 ; no, root device
  5135                              <1> 	; yes, mounted device
  5136                              <1> 	;mov	edx, mmod
  5137 00004D89 42                  <1> 	inc	edx ; edx = offset mmod
  5138                              <1> maknod4: 
  5139 00004D8A FE02                <1> 	inc	byte [edx] ; superblock modified !
  5140                              <1> 
  5141                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5142                              <1> 	;;
  5143                              <1> 	;; 27/03/2021
  5144                              <1> 	;; (ref: 'UNIXHDCP.ASM', 'mak_nod', 18/01/2020)
  5145                              <1> 	;or	byte [smod], 2 ; inode map modified
  5146                              <1> 	;; 01/04/2021
  5147                              <1> 	;;or	byte [imapbuf_hdr+bufhdr.status], 2
  5148                              <1> 	;or	byte [imapbuf_hdr], 2 ; set modified flag bit
  5149                              <1> 	; 02/05/2021
  5150                              <1> 	;or	byte [esi+ldrv.b_status], 2 ; inode map modified
  5151                              <1> 	; 15/08/2021
  5152                              <1> 	; 06/05/2021
  5153                              <1> 	;or	byte [esi+ldrv.status], 2 ; inode map modified
  5154                              <1> 	;;or	byte [sysbuf_hdr], 2 ; set modified flag bit
  5155                              <1> 	
  5156                              <1> 	;mov	eax, [ebp+SB.LastInode] ; (free) inode number
  5157                              <1> 	;push	eax ; ***
  5158                              <1> 
  5159                              <1> 	; 12/03/2022
  5160                              <1> 	; increase first free inode number
  5161 00004D8C 8B0424              <1> 	mov	eax, [esp] ; ***
  5162 00004D8F 40                  <1> 	inc	eax ; next inode number 
  5163                              <1> 		    ; (free inode search start value)
  5164 00004D90 894534              <1> 	mov	[ebp+SB.FirstFreeIno], eax
  5165                              <1> 
  5166                              <1> 	; 12/03/2022
  5167                              <1> 	; decrease free inode count
  5168 00004D93 8B5530              <1> 	mov	edx, [ebp+SB.FreeInodes]
  5169                              <1> 	;cmp	edx, 0FFFFFFFFh
  5170                              <1> 	;je	short maknod5 ; invalid
  5171 00004D96 42                  <1> 	inc	edx ; 0FFFFFFFFh -> 0
  5172 00004D97 7405                <1> 	jz	short maknod5 ; invalid
  5173 00004D99 4A                  <1> 	dec	edx
  5174 00004D9A 4A                  <1> 	dec	edx
  5175 00004D9B 895530              <1> 	mov	[ebp+SB.FreeInodes], edx ; -1
  5176                              <1> maknod5:
  5177 00004D9E E8C3150000          <1> 	call	get_system_time
  5178                              <1> 		; eax = current time (as unix epoch time)
  5179 00004DA3 89455C              <1> 	mov	[ebp+SB.ModifTime], eax
  5180                              <1> 
  5181 00004DA6 58                  <1> 	pop	eax ; *** ; inode number
  5182                              <1> 	;;
  5183 00004DA7 E869070000          <1> 	call	iget
  5184                              <1> 		; jsr r0,iget / get i-node into core
  5185                              <1> 	; 09/01/2022
  5186                              <1> 	;  (If cpu is here, there was/is not an error!)
  5187                              <1> 	; 06/11/2021
  5188                              <1> 	;jc	short maknod_err
  5189                              <1> 	
  5190                              <1> 	;test	word [i.flgs], 8000h 
  5191                              <1> 	;	; tst i.flgs / is i-node already allocated
  5192                              <1> 	;jnz	short maknod1	
  5193                              <1> 	;	; blt 1b / yes, look for another one
  5194                              <1> 	; 27/03/2021
  5195                              <1> 	; (Retro UNIX 386 v2 inode flags) 
  5196 00004DAC F605[59710000]E0    <1> 	test	byte [i.flgs+1], 0E0h ; 80h+40h+20h
  5197                              <1> 	;jnz	short maknod1 ; i-node already allocated
  5198                              <1> 	;		      ; (as it is in inode table)
  5199                              <1> 	; 15/08/2021
  5200 00004DB3 75A6                <1> 	jnz	short maknod2 ; defective inode map !?
  5201                              <1> 
  5202                              <1> 	; AX = free inode number
  5203 00004DB5 66A3[E4750000]      <1> 	mov	[u.dirbuf], ax
  5204                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  5205 00004DBB 58                  <1> 	pop	eax ; **** (parent) ; 27/03/2021 (32 bit push, pop)
  5206                              <1> 		; mov (sp)+,r1 / get current i-number back
  5207 00004DBC E854070000          <1> 	call	iget
  5208                              <1> 		; jsr r0,iget / get i-node in core
  5209                              <1> 	; 09/01/2022
  5210                              <1> 	; 06/11/2021
  5211                              <1> 	;jc	short maknod_err
  5212                              <1> 
  5213                              <1> 	; 14/02/2022
  5214                              <1> 	; here..
  5215                              <1> 	;  [u.namep] points to the file name address
  5216                              <1> 	;	     (in the user's memory space)
  5217                              <1> 	;  [u.dirp] points to empty slot in the directory
  5218                              <1> 
  5219 00004DC1 E86AF7FFFF          <1> 	call	mkdir
  5220                              <1> 		; jsr r0,mkdir / make a directory entry 
  5221                              <1> 			     ; / in current directory
  5222                              <1> 	; 09/01/2022
  5223                              <1> 	;  (If cpu is here, there was/is not an error in 'mkdir'!)
  5224                              <1> 	; 06/11/2021
  5225                              <1> 	;jc	short maknod_err
  5226                              <1> 	
  5227                              <1> 	; (eax = 0)
  5228                              <1> 	;movzx	eax, [u.difbuf] ; 06/11/2021
  5229 00004DC6 66A1[E4750000]      <1> 	mov	ax, [u.dirbuf]
  5230                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  5231 00004DCC E844070000          <1> 	call	iget
  5232                              <1> 		; jsr r0,iget / get it into core
  5233                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  5234                              <1> 	; 09/01/2022
  5235                              <1> 	; 06/11/2021
  5236                              <1> 	;jc	short maknod_err
  5237                              <1> 
  5238                              <1> 	;mov	ecx, 8
  5239                              <1> 	; 27/03/2021
  5240 00004DD1 31C9                <1> 	xor	ecx, ecx 
  5241 00004DD3 B110                <1> 	mov	cl, 16 ; 64 bit inodes
  5242 00004DD5 31C0                <1> 	xor	eax, eax ; 0
  5243 00004DD7 BF[58710000]        <1> 	mov	edi, inode 
  5244 00004DDC F3AB                <1> 	rep	stosd
  5245                              <1> 	;
  5246                              <1> 	;pop	word [i.flgs]
  5247                              <1> 	;	; mov (sp)+,i.flgs / fill flags
  5248                              <1> 	; 27/03/2021 (32 bit push, pop)
  5249 00004DDE 58                  <1> 	pop	eax ; *****
  5250 00004DDF 66A3[58710000]      <1> 	mov	[i.flgs], ax
  5251                              <1> 
  5252                              <1> 	;mov 	cl, [u.uid] ; 02/08/2013
  5253                              <1> 	;mov 	[i.uid], cl
  5254                              <1> 	;	; movb u.uid,i.uid / user id
  5255                              <1> 	; 15/08/2021
  5256                              <1> 	; 27/03/2021
  5257 00004DE5 8A0D[02760000]      <1> 	mov	cl, [u.gid] ; 8 bit group ID ; 15/08/2021
  5258 00004DEB 880D[5E710000]      <1> 	mov	[i.gid], cl 	
  5259 00004DF1 668B0D[FE750000]    <1> 	mov	cx, [u.uid] ; 16 bit user ID
  5260 00004DF8 66890D[5C710000]    <1> 	mov	[i.uid], cx	
  5261                              <1> 
  5262 00004DFF C605[5A710000]01    <1> 	mov     byte [i.nlks], 1
  5263                              <1> 		; movb $1,i.nlks / 1 link
  5264                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  5265                              <1> 	;mov	eax, [s.time]
  5266                              <1> 	;mov 	[i.ctim], eax
  5267                              <1> 	 	; mov s.time,i.ctim / time created
  5268                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  5269                              <1> 	; Retro UNIX 8086 v1 modification !
  5270                              <1> 	; i.ctime=0, i.ctime+2=0 and
  5271                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  5272                              <1> 	;call	setimod
  5273                              <1> 	;	; jsr r0,setimod / set modified flag
  5274                              <1> 	;retn
  5275                              <1> 	;	; rts r0 / return
  5276                              <1> 	; 27/03/2021
  5277 00004E06 E99B080000          <1> 	jmp	setimod
  5278                              <1> 
  5279                              <1> sysseek: ; / moves read write pointer in an fsp entry
  5280                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5281                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5282                              <1> 	;
  5283                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  5284                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  5285                              <1> 	; The file descriptor refers to a file open for reading or
  5286                              <1> 	; writing. The read (or write) pointer is set as follows:
  5287                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  5288                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  5289                              <1> 	;	  current location plus offset.
  5290                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  5291                              <1> 	;	  size of file plus offset.
  5292                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  5293                              <1> 	;
  5294                              <1> 	; Calling sequence:
  5295                              <1> 	;	sysseek; offset; ptrname
  5296                              <1> 	; Arguments:
  5297                              <1> 	;	offset - number of bytes desired to move 
  5298                              <1> 	;		 the r/w pointer
  5299                              <1> 	;	ptrname - a switch indicated above
  5300                              <1> 	;
  5301                              <1> 	; Inputs: r0 - file descriptor 
  5302                              <1> 	; Outputs: -
  5303                              <1> 	; ...............................................................
  5304                              <1> 	;	
  5305                              <1> 	; Retro UNIX 8086 v1 modification: 
  5306                              <1> 	;       'sysseek' system call has three arguments; so,
  5307                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  5308                              <1> 	;	* 2nd argument, offset is in CX register
  5309                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  5310                              <1> 	;	
  5311                              <1> 
  5312 00004E0B E820000000          <1> 	call	seektell
  5313                              <1> 	; AX = u.count
  5314                              <1> 	; BX = *u.fofp
  5315                              <1> 		; jsr r0,seektell / get proper value in u.count
  5316                              <1> 		; add u.base,u.count / add u.base to it
  5317 00004E10 0305[D0750000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  5318 00004E16 8903                <1> 	mov	[ebx], eax
  5319                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  5320 00004E18 E94BEDFFFF          <1> 	jmp	sysret
  5321                              <1> 		; br sysret4
  5322                              <1> 
  5323                              <1> systell: ; / get the r/w pointer
  5324                              <1> 	; 01/03/2022
  5325                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5326                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5327                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5328                              <1> 	;
  5329                              <1> 	; Retro UNIX 8086 v1 modification:
  5330                              <1> 	; ! 'systell' does not work in original UNIX v1,
  5331                              <1> 	; 	    it returns with error !
  5332                              <1> 	; Inputs: r0 - file descriptor 
  5333                              <1> 	; Outputs: r0 - file r/w pointer
  5334                              <1> 
  5335                              <1> 	;xor	ecx, ecx ; 0
  5336                              <1> 	;mov	edx, 1 ; 05/08/2013
  5337                              <1> 	; 09/01/2022
  5338 00004E1D 29D2                <1> 	sub	edx, edx
  5339 00004E1F FEC2                <1> 	inc	dl
  5340                              <1> 	; edx = 1
  5341                              <1> 	;call 	seektell
  5342 00004E21 E810000000          <1> 	call 	seektell0 ; 05/08/2013
  5343                              <1> 	;mov	ebx, [u.fofp]
  5344                              <1> 	; 01/03/2022
  5345                              <1> 	;mov	eax, [ebx]
  5346 00004E26 A3[AC750000]        <1> 	mov	[u.r0], eax
  5347 00004E2B E938EDFFFF          <1> 	jmp	sysret
  5348                              <1> 
  5349                              <1> ; Original unix v1 'systell' system call:
  5350                              <1> 		; jsr r0,seektell
  5351                              <1> 		; br error4
  5352                              <1> 
  5353                              <1> seektell:
  5354                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5355                              <1> 	; 06/11/2021
  5356                              <1> 	; 12/06/2021
  5357                              <1> 	; 06/05/2021 (Retro UNIX 386 v2)
  5358                              <1> 	; 03/01/2016
  5359                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5360                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5361                              <1> 	;
  5362                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  5363                              <1> 	; call in u.base and u.count. It then gets the i-number of
  5364                              <1> 	; the file from the file descriptor in u.r0 and by calling
  5365                              <1> 	; getf. The i-node is brought into core and then u.count
  5366                              <1> 	; is checked to see it is a 0, 1, or 2.
  5367                              <1> 	; If it is 0 - u.count stays the same
  5368                              <1> 	;          1 - u.count = offset (u.fofp)
  5369                              <1> 	;	   2 - u.count = i.size (size of file)
  5370                              <1> 	; 	 		
  5371                              <1> 	; !! Retro UNIX 8086 v1 modification:
  5372                              <1> 	;	Argument 1, file descriptor is in BX;
  5373                              <1> 	;	Argument 2, offset is in CX;
  5374                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  5375                              <1> 	;
  5376                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  5377                              <1> 	; call 	arg
  5378                              <1> 	;
  5379                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  5380                              <1> 	;
  5381 00004E30 890D[D0750000]      <1> 	mov 	[u.base], ecx ; offset
  5382                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  5383                              <1> 	; 09/01/2022
  5384                              <1> 	; ebx = file descriptor (0 to 9)
  5385                              <1> seektell0:
  5386 00004E36 8915[D4750000]      <1> 	mov 	[u.count], edx
  5387                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  5388                              <1> 	;mov	ax, bx
  5389                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  5390                              <1> 			     ; / (index in u.fp list)
  5391                              <1> 	; 12/06/2021
  5392                              <1> 	; BX = file descriptor (file number)
  5393 00004E3C E8E1FBFFFF          <1> 	call	getf
  5394                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  5395                              <1> 	; 09/01/2022
  5396 00004E41 09C0                <1> 	or	eax, eax
  5397                              <1> 	;or	ax, ax ; i-number of the file
  5398                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  5399                              <1> 		             ; / put it on the stack
  5400                              <1> 	;jz	error
  5401                              <1> 		; beq error4 / if i-number is 0, not active so error
  5402 00004E43 750F                <1> 	jnz	short seektell1
  5403 00004E45 C705[20760000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  5403 00004E4D 0000                <1>
  5404 00004E4F E9F4ECFFFF          <1> 	jmp	error
  5405                              <1> seektell1:
  5406                              <1> 	; 06/05/2021
  5407                              <1> 	;push	eax
  5408                              <1> 	;cmp	ah, 80h
  5409                              <1> 	;jb	short seektell2
  5410                              <1> 	;	; bgt .+4 / if its positive jump
  5411                              <1> 	;neg	ax
  5412                              <1> 	;	; neg r1 / if not make it positive
  5413                              <1> seektell2:
  5414 00004E54 E8BC060000          <1> 	call	iget
  5415                              <1> 		; jsr r0,iget / get its i-node into core
  5416                              <1> 	; 09/01/2022
  5417                              <1> 	; (if there is/was an error in 'iget', cpu will not come here)
  5418                              <1> 	;; 06/11/2021
  5419                              <1> 	;jnc	short seektell6
  5420                              <1> 	;mov	[u.error], eax
  5421                              <1> 	;jmp	error
  5422                              <1> seektell6:
  5423 00004E59 8B1D[C0750000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  5424 00004E5F 803D[D4750000]01    <1> 	cmp	byte [u.count], 1
  5425                              <1> 		; cmp u.count,$1 / is ptr name =1
  5426 00004E66 7705                <1> 	ja	short seektell3
  5427                              <1> 		; blt 2f / no its zero
  5428 00004E68 7409                <1> 	je	short seektell4
  5429                              <1> 		; beq 1f / yes its 1
  5430 00004E6A 31C0                <1> 	xor	eax, eax
  5431                              <1> 	;jmp	short seektell5
  5432 00004E6C C3                  <1> 	retn
  5433                              <1> seektell3:
  5434                              <1> 	; 03/01/2016
  5435                              <1> 	;;movzx	eax, word [i.size]
  5436                              <1> 	;mov   	ax, [i.size]
  5437                              <1> 	;	; mov i.size,u.count /  put number of bytes 
  5438                              <1> 	;			; / in file in u.count
  5439                              <1> 	;;jmp	short seektell5
  5440                              <1> 	;	; br 2f
  5441                              <1> 	; 06/05/2021 - Retro UNIX 386 v2
  5442 00004E6D A1[60710000]        <1> 	mov	eax, [i.size]
  5443 00004E72 C3                  <1> 	retn
  5444                              <1> seektell4: ; 1: / ptrname =1
  5445                              <1> 	;mov	ebx, [u.fofp]
  5446 00004E73 8B03                <1> 	mov	eax, [ebx]
  5447                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  5448                              <1> ;seektell5: ; 2: / ptrname =0
  5449                              <1> 	;mov	[u.count], eax
  5450                              <1> 	;pop	eax 
  5451                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  5452 00004E75 C3                  <1> 	retn
  5453                              <1> 		; rts r0
  5454                              <1> 
  5455                              <1> sysintr: ; / set interrupt handling
  5456                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5457                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5458                              <1> 	;
  5459                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  5460                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  5461                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  5462                              <1> 	; If one does the interrupt character in the tty buffer is
  5463                              <1> 	; cleared and 'sysret'is called. If one does not exits
  5464                              <1> 	; 'sysret' is just called.	
  5465                              <1> 	;
  5466                              <1> 	; Calling sequence:
  5467                              <1> 	;	sysintr; arg
  5468                              <1> 	; Argument:
  5469                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  5470                              <1> 	;	    - if 1, intterupts cause their normal result
  5471                              <1> 	;		 i.e force an exit.
  5472                              <1> 	;	    - if arg is a location within the program,
  5473                              <1> 	;		control is passed to that location when
  5474                              <1> 	;		an interrupt occurs.	
  5475                              <1> 	; Inputs: -
  5476                              <1> 	; Outputs: -
  5477                              <1> 	; ...............................................................
  5478                              <1> 	;	
  5479                              <1> 	; Retro UNIX 8086 v1 modification: 
  5480                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  5481                              <1> 	;	then branches into sysquit.
  5482                              <1> 	;
  5483 00004E76 66891D[F8750000]    <1> 	mov	[u.intr], bx
  5484                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  5485                              <1> 		; br 1f / go into quit routine
  5486 00004E7D E9E6ECFFFF          <1> 	jmp	sysret
  5487                              <1> 
  5488                              <1> sysquit:
  5489                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5490                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5491                              <1> 	;
  5492                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  5493                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  5494                              <1> 	; tty exists. If one does the interrupt character in the tty
  5495                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  5496                              <1> 	; 'sysret' is just called.	
  5497                              <1> 	;
  5498                              <1> 	; Calling sequence:
  5499                              <1> 	;	sysquit; arg
  5500                              <1> 	; Argument:
  5501                              <1> 	;	arg - if 0, this call disables quit signals from the
  5502                              <1> 	;		typewriter (ASCII FS)
  5503                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  5504                              <1> 	;		cease and a core image to be produced.
  5505                              <1> 	;		 i.e force an exit.
  5506                              <1> 	;	    - if arg is an address in the program,
  5507                              <1> 	;		a quit causes control to sent to that
  5508                              <1> 	;		location.	
  5509                              <1> 	; Inputs: -
  5510                              <1> 	; Outputs: -
  5511                              <1> 	; ...............................................................
  5512                              <1> 	;	
  5513                              <1> 	; Retro UNIX 8086 v1 modification: 
  5514                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  5515                              <1> 	;	then branches into 'sysret'.
  5516                              <1> 	;
  5517 00004E82 66891D[FA750000]    <1> 	mov	[u.quit], bx
  5518 00004E89 E9DAECFFFF          <1> 	jmp	sysret
  5519                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  5520                              <1> 	;1:
  5521                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  5522                              <1> 			      ; / to r1
  5523                              <1> 		; beq sysret4 / return to user
  5524                              <1> 		; clrb 6(r1) / clear the interrupt character 
  5525                              <1> 			   ; / in the tty buffer
  5526                              <1> 		; br sysret4 / return to user
  5527                              <1> 
  5528                              <1> syssetuid: ; / set process id
  5529                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5530                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5531                              <1> 	;		(16 bit uid)
  5532                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5533                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  5534                              <1> 	;
  5535                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  5536                              <1> 	; to the process id in (u.r0). Both the effective user u.uid
  5537                              <1> 	; and the real user u.ruid are set to this. 
  5538                              <1> 	; Only the super user can make this call.	
  5539                              <1> 	;
  5540                              <1> 	; Calling sequence:
  5541                              <1> 	;	syssetuid
  5542                              <1> 	; Arguments: -
  5543                              <1> 	;
  5544                              <1> 	; Inputs: (u.r0) - contains the process id.
  5545                              <1> 	; Outputs: -
  5546                              <1> 	; ...............................................................
  5547                              <1> 	;	
  5548                              <1> 	; Retro UNIX 8086 v1 modification: 
  5549                              <1> 	;       BL contains the (new) user ID of the current process
  5550                              <1> 
  5551                              <1> 	; 27/03/2021
  5552                              <1> 	; INPUT:
  5553                              <1> 	;    BX = (new) user ID
  5554                              <1> 
  5555                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  5556                              <1> 	;cmp	bl, [u.ruid] 
  5557                              <1> 	;	; cmpb r1,u.ruid / is it equal to the real user 
  5558                              <1> 			       ; / id number
  5559                              <1> 	; 27/03/2021
  5560 00004E8E 663B1D[00760000]    <1> 	cmp	bx, [u.ruid]
  5561 00004E95 7420                <1> 	je	short setuid1
  5562                              <1> 		; beq 1f / yes
  5563                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  5564                              <1> 	;	; tstb u.uid / no, is current user the super user?
  5565                              <1> 	;;ja	error
  5566                              <1> 	;	; bne error4 / no, error
  5567                              <1> 	; 27/03/2021
  5568 00004E97 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0 
  5569 00004E9F 760F                <1> 	jna	short setuid0
  5570                              <1> setuid_err:
  5571                              <1> setgid_err:
  5572 00004EA1 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  5572 00004EA9 0000                <1>
  5573                              <1> 				; 'permission denied !' error
  5574 00004EAB E998ECFFFF          <1> 	jmp	error
  5575                              <1> setuid0:
  5576                              <1> 	;mov	[u.ruid], bl
  5577                              <1> 	; 27/03/2021
  5578 00004EB0 66891D[00760000]    <1> 	mov	[u.ruid], bx
  5579                              <1> setuid1: ; 1:
  5580                              <1> 	;mov	[u.uid], bl ; 02/08/2013
  5581                              <1> 	;	; movb r1,u.uid / put process id in u.uid
  5582                              <1> 	;	; movb r1,u.ruid / put process id in u.ruid
  5583                              <1> 	; 27/03/2021
  5584 00004EB7 66891D[FE750000]    <1> 	mov	[u.uid], bx
  5585 00004EBE E9A5ECFFFF          <1> 	jmp	sysret
  5586                              <1> 		; br sysret4 / system return
  5587                              <1> 
  5588                              <1> sysgetuid: ; < get user id >
  5589                              <1> 	; 11/03/2022
  5590                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5591                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5592                              <1> 	;		(16 bit uid)
  5593                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5594                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5595                              <1> 	;
  5596                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  5597                              <1> 	; The real user ID identifies the person who is logged in,
  5598                              <1> 	; in contradistinction to the effective user ID, which
  5599                              <1> 	; determines his access permission at each moment. It is thus
  5600                              <1> 	; useful to programs which operate using the 'set user ID'
  5601                              <1> 	; mode, to find out who invoked them.	
  5602                              <1> 	;
  5603                              <1> 	; Calling sequence:
  5604                              <1> 	;	syssetuid
  5605                              <1> 	; Arguments: -
  5606                              <1> 	;
  5607                              <1> 	; Inputs: -
  5608                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  5609                              <1> 	; ...............................................................
  5610                              <1> 	;	
  5611                              <1> 	; Retro UNIX 8086 v1 modification: 
  5612                              <1> 	;       AL contains the real user ID at return.
  5613                              <1> 	;
  5614                              <1> 	; 11/03/2022 - Retro UNIX 386 v1.2
  5615                              <1> 	; Input:
  5616                              <1> 	;	none
  5617                              <1> 	; Output/Return:
  5618                              <1> 	;	AX = real user ID
  5619                              <1> 	;	Hig Word of EAX = effective user ID
  5620                              <1> 
  5621                              <1> 	;;movzx eax, byte [u.ruid]
  5622                              <1> 	; 27/03/2021
  5623                              <1> 	;movzx	eax, word [u.ruid]
  5624                              <1> 	; 11/03/2022
  5625                              <1> 	; (return u.uid & u.ruid numbers as it is in unix v5-v7)
  5626 00004EC3 66A1[FE750000]      <1> 	mov	ax, [u.uid]
  5627 00004EC9 C1E010              <1> 	shl	eax, 16	; efective user ID in high word of eax
  5628                              <1> 	; 09/01/2022
  5629 00004ECC 66A1[00760000]      <1> 	mov	ax, [u.ruid] ; real user ID in low word of eax
  5630 00004ED2 A3[AC750000]        <1> 	mov	[u.r0], eax 
  5631                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  5632 00004ED7 E98CECFFFF          <1> 	jmp	sysret
  5633                              <1> 		; br sysret4 / systerm return, sysret
  5634                              <1> 
  5635                              <1> syssetgid: ; set group id
  5636                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5637                              <1> 	; 02/04/2021
  5638                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5639                              <1> 	;
  5640                              <1> 	; 'syssetgid' sets the user's group id (u.gid) 
  5641                              <1> 	;  of the current process to the process id in (u.r0).
  5642                              <1> 	;  Both the effective user u.gid and the real user
  5643                              <1> 	;  u.rgid are set to this. 
  5644                              <1> 	;  Only the super user can make this call.	
  5645                              <1> 	
  5646                              <1> 	; INPUT:
  5647                              <1> 	;	BL = (new) group ID
  5648                              <1> 	; OUTPUT:
  5649                              <1> 	;	-
  5650                              <1> 
  5651 00004EDC 3A1D[03760000]      <1> 	cmp	bl, [u.rgid] 
  5652 00004EE2 7410                <1> 	je	short setgid1
  5653                              <1> 
  5654                              <1> 	;cmp	byte [u.uid], 0
  5655                              <1> 	; 02/04/2021
  5656 00004EE4 66833D[FE750000]00  <1> 	cmp	word [u.uid], 0
  5657 00004EEC 77B3                <1> 	ja	short setgid_err
  5658                              <1> setgid0:
  5659 00004EEE 881D[03760000]      <1> 	mov	[u.rgid], bl
  5660                              <1> setgid1: ; 1:
  5661 00004EF4 881D[02760000]      <1> 	mov	[u.gid], bl
  5662 00004EFA E969ECFFFF          <1> 	jmp	sysret
  5663                              <1> 
  5664                              <1> sysgetgid: ; < get group id >
  5665                              <1> 	; 11/03/2022
  5666                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5667                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5668                              <1> 	;
  5669                              <1> 	; 'sysgetgid' returns the real group ID of the current process.
  5670                              <1> 	; The real group ID identifies the group of the person
  5671                              <1> 	; who is logged in, in contradistinction to the effective
  5672                              <1> 	; group ID, which determines his access permission at each moment.
  5673                              <1> 	; It is thus useful to programs which operate using
  5674                              <1> 	; the 'set group ID' mode, to find out the group of the user
  5675                              <1> 	; who invoked them.
  5676                              <1> 
  5677                              <1> 	; 11/03/2022 - Retro UNIX 386 v1.2
  5678                              <1> 	; Input:
  5679                              <1> 	;	none
  5680                              <1> 	; Output/Return:
  5681                              <1> 	;	AL = real group ID
  5682                              <1> 	;	AH = effective group ID
  5683                              <1> 
  5684                              <1> 	;movzx	eax, word [u.ruid]
  5685                              <1> 	;; 09/01/2022
  5686                              <1> 	;mov	ax, [u.ruid]
  5687                              <1> 	; 11/03/2022
  5688                              <1> 	; (return u.gid & u.rgid numbers as it is in unix v5-v7)
  5689 00004EFF 8A25[02760000]      <1> 	mov	ah, [u.gid] ; efective group ID in byte 1
  5690 00004F05 A0[03760000]        <1> 	mov	al, [u.rgid] ; real group ID in byte 0
  5691 00004F0A A3[AC750000]        <1> 	mov	[u.r0], eax
  5692 00004F0F E954ECFFFF          <1> 	jmp	sysret
  5693                              <1> 
  5694                              <1> sysver: ; get operating system version
  5695                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5696                              <1> 	; 18/06/2021 - Retro UNIX 386 v2
  5697                              <1> 
  5698                              <1> 	;VMAJOR equ 2 ; Retro UNIX 386 v2
  5699                              <1> 	;VMINOR equ 0 ; Retro UNIX 386 v2.0 (v2.0.0)
  5700                              <1> 	;CURRENT_VERSION equ (VMAJOR*256)+VMINOR
  5701                              <1> 
  5702                              <1> 	; 09/01/2022
  5703                              <1> 	VMAJOR equ 1 ; Retro UNIX 386 v1
  5704                              <1> 	VMINOR equ 2 ; Retro UNIX 386 v1.2 (v1.2.0)
  5705                              <1> 	CURRENT_VERSION equ (VMAJOR*256)+VMINOR 		  
  5706                              <1> 
  5707                              <1> 	; 29/04/2016 - TRDOS 386 v2.0
  5708                              <1> 	;mov	dword [u.r0], 200h ; AH = major version, AL = minor version 
  5709                              <1> 	; 18/06/2021
  5710 00004F14 C705[AC750000]0201- <1> 	mov	dword [u.r0], CURRENT_VERSION ;	(ah = 2, al = 0)
  5710 00004F1C 0000                <1>
  5711 00004F1E E945ECFFFF          <1> 	jmp	sysret
  5712                              <1> 
  5713                              <1> anyi: 
  5714                              <1> 	; 26/03/2022
  5715                              <1> 	; 13/03/2022
  5716                              <1> 	; 12/03/2022
  5717                              <1> 	; 09/01/2022
  5718                              <1> 	; 02/01/2022
  5719                              <1> 	; 01/01/2022
  5720                              <1> 	; 27/12/2021 (Retro UNIX 386 v1.2)
  5721                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  5722                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5723                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  5724                              <1> 	;
  5725                              <1> 	; 'anyi' is called if a file deleted while open.
  5726                              <1> 	; "anyi" checks to see if someone else has opened this file.
  5727                              <1> 	;
  5728                              <1> 	; INPUTS ->
  5729                              <1> 	;    r1 - contains an i-number
  5730                              <1> 	;    fsp - start of table containing open files
  5731                              <1> 	;
  5732                              <1> 	; OUTPUTS ->
  5733                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  5734                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  5735                              <1> 	;    if file not found - bit in i-node map is cleared
  5736                              <1> 	;    			 (i-node is freed)
  5737                              <1> 	;               all blocks related to i-node are freed
  5738                              <1> 	;	        all flags in i-node are cleared
  5739                              <1> 	; ((AX = R1)) input
  5740                              <1> 	;
  5741                              <1> 	;    (Retro UNIX Prototype: 02/12/2012, UNIXCOPY.ASM)
  5742                              <1> 	;	12/03/2022
  5743                              <1>         ;    ((Modified registers: eax, edx, ecx, ebx, esi, edi, ebp))  
  5744                              <1> 	;
  5745                              <1> 		; / r1 contains an i-number
  5746 00004F23 BB[48720000]        <1> 	mov	ebx, fsp
  5747                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  5748                              <1> anyi_1: ; 1:
  5749                              <1> 	;cmp	eax, [ebx] ; 09/01/2022 (32 bit inode number)
  5750 00004F28 663B03              <1> 	cmp	ax, [ebx]
  5751                              <1> 		; cmp r1,(r2) / do i-numbers match?
  5752                              <1> 	;je	short anyi_3
  5753                              <1> 		; beq 1f / yes, 1f
  5754                              <1> 	; 12/03/2022
  5755 00004F2B 7505                <1> 	jne	short anyi_0		
  5756                              <1> 
  5757                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5758                              <1> 	;neg	ax
  5759                              <1> 	;	; neg r1 / no complement r1
  5760                              <1> 	;cmp	ax, [ebx]
  5761                              <1> 	;	; cmp r1,(r2) / do they match now?
  5762                              <1> 	;;je	short anyi_3
  5763                              <1> 		; beq 1f / yes, transfer
  5764                              <1> 		; / i-numbers do not match
  5765                              <1> 	; 12/03/2022
  5766                              <1> 	;jne	short ayni_0
  5767                              <1> 
  5768                              <1> anyi_3: ; 1: / i-numbers match
  5769                              <1> 	; 13/03/2022 (BugFix)
  5770                              <1> 	;; 09/01/2022
  5771                              <1> 	;test	byte [ebx+5], 1 ; open for writing flag
  5772                              <1> 	;jz	short anyi_0	
  5773                              <1> 
  5774                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5775 00004F2D 804B0580            <1> 	or	byte [ebx+5], 80h ; set deleted file flag (bit 7)
  5776                              <1> 	; 22/06/2015
  5777                              <1> 	;inc 	byte [ebx+9]
  5778                              <1> 		; incb 7(r2) / increment upper byte of the 4th word
  5779                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  5780 00004F31 C3                  <1> 	retn
  5781                              <1> 		; rts r0
  5782                              <1> anyi_0:
  5783                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5784                              <1> 	;add	ebx, fp.size ; runix v2 fsp table size is 16 bytes
  5785                              <1> 	; 01/01/2022
  5786 00004F32 83C310              <1> 	add	ebx, 16 ; runix v2 fsp table size is 16 bytes
  5787                              <1> 	;;add	ebx, 10 ; fsp table size is 10 bytes
  5788                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  5789                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  5790                              <1> 	; 22/11/2021
  5791                              <1> 	;cmp	ebx, fsp + (NFILES*fp.size) ; fsp+(NFILES*16)
  5792                              <1> 	; 02/01/2022
  5793 00004F35 81FB[68750000]      <1> 	cmp	ebx, fsp + (nfiles*16)
  5794                              <1> 	; 01/01/2022
  5795                              <1> 	;cmp	ebx, fsp + (NFILES*16) ; fsp+(NFILES*fp.size)
  5796                              <1> 	;;cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  5797                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  5798                              <1> 			; / are we at last entry in the table
  5799 00004F3B 72EB                <1> 	jb	short anyi_1
  5800                              <1> 		; blt 1b / no, check next entries i-number
  5801                              <1> 
  5802                              <1> 	; 27/12/2021
  5803                              <1> 	;;cmp	ax, 32768
  5804                              <1> 	;cmp	ah, 80h ; negative number check
  5805                              <1> 	;	; tst r1 / yes, no match
  5806                              <1> 	;	; bge .+4
  5807                              <1> 	;jb	short anyi_2
  5808                              <1> 	;neg	ax
  5809                              <1> 	;	; neg r1 / make i-number positive
  5810                              <1> ;anyi_2:	
  5811                              <1> 	; 12/03/2022
  5812                              <1> 	;push	eax ; **** ; inode number
  5813                              <1> 	;
  5814 00004F3D E8B2080000          <1> 	call	imap
  5815                              <1> 		; jsr r0,imap / get address of allocation bit 
  5816                              <1> 			    ; / in the i-map in r2
  5817                              <1> 
  5818                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  5819                              <1>         ;; EBX (R2) has address of the byte with allocation bit
  5820                              <1> 
  5821                              <1> 	; 12/03/2022
  5822                              <1> 	; (at return of imap)
  5823                              <1> 	; ebp = superblock buffer address
  5824                              <1> 	; eax = inode number
  5825                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  5826                              <1> 	;			of current IMAP sector
  5827                              <1> 	; EBX = buffer address/offset for relevant alloc byte
  5828                              <1> 	;  DL has 1 at bit position which is for free inode
  5829                              <1> 	;
  5830                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  5831                              <1> 
  5832                              <1>  	;;not	dx
  5833                              <1> 	;not 	dl ; 0 at calculated bit position, other bits are 1
  5834                              <1>         ;;and	[ebx], dx
  5835                              <1> 	;and 	[ebx], dl 
  5836                              <1> 	;	; bicb mq,(r2) / clear bit for i-node in the imap
  5837                              <1> 
  5838                              <1> 	; 12/03/2022 ; (*)
  5839                              <1> 
  5840                              <1> 	;mov	[ebp+SB.LastInode], eax ; (free) inode number
  5841                              <1> 
  5842 00004F42 50                  <1> 	push	eax ; ***
  5843 00004F43 51                  <1> 	push	ecx ; **
  5844 00004F44 52                  <1> 	push	edx ; *
  5845 00004F45 55                  <1> 	push	ebp ; @ ; 11/03/2022
  5846                              <1> 
  5847 00004F46 8B457C              <1> 	mov	eax, [ebp+SB.ImapBuffer]
  5848                              <1> 
  5849 00004F49 E834130000          <1> 	call	wslot
  5850                              <1> 	; ebx = buffer data address (write operation bit is set)
  5851                              <1> 	; eax = physical sector number
  5852                              <1> 	; Note: ebx contains addr of the 1st buffer in the buf chain
  5853                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  5854 00004F4E 5D                  <1> 	pop	ebp ; @ ; 11/03/2022
  5855                              <1> 
  5856                              <1> 	;mov	[ebp+SB.ImapBuffer], ebx
  5857                              <1> 			; save inode map buffer address
  5858 00004F4F 5A                  <1> 	pop	edx ; *
  5859 00004F50 59                  <1> 	pop	ecx ; **
  5860 00004F51 01CB                <1> 	add	ebx, ecx ; + byte offset (for allocation bit pos)	
  5861                              <1> 
  5862                              <1> 	;not	dx
  5863 00004F53 F6D2                <1> 	not 	dl ; 0 at calculated bit position, other bits are 1
  5864                              <1>         ;and	[ebx], dx
  5865 00004F55 2013                <1> 	and 	[ebx], dl 
  5866                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  5867                              <1> 
  5868                              <1> 	;push	ebp ; @
  5869 00004F57 E842130000          <1> 	call	dskwr ; writes the 1st buffer to sector
  5870                              <1> 		      ; (at the beginning/head of the buffer chain)
  5871                              <1> 	;pop	ebp ; @
  5872                              <1> 
  5873                              <1> 	; if we are here, buffer has been written to disk successfully 
  5874                              <1> 	; (otherwise cpu would jump to 'error' address)
  5875                              <1> 
  5876                              <1> 	; 12/03/2022 ; (*)
  5877                              <1> 	; set superblock modified flag
  5878 00004F5C BA[A0750000]        <1> 	mov	edx, smod
  5879 00004F61 F605[8D750000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  5880 00004F68 7401                <1> 	jz	short anyi_2 ; no, root device
  5881                              <1> 	; yes, mounted device
  5882 00004F6A 42                  <1> 	inc	edx ; edx = offset mmod
  5883                              <1> anyi_2:
  5884 00004F6B FE02                <1> 	inc	byte [edx] ; superblock modified !
  5885                              <1> 
  5886                              <1> 	; 12/03/2022
  5887                              <1> 	; decrease first free inode number (if it is required)
  5888 00004F6D 8B0424              <1> 	mov	eax, [esp] ; ***
  5889                              <1> 	; eax = released/freed inode number 
  5890 00004F70 394534              <1> 	cmp	[ebp+SB.FirstFreeIno], eax
  5891 00004F73 7603                <1> 	jna	short anyi_4
  5892 00004F75 894534              <1> 	mov	[ebp+SB.FirstFreeIno], eax
  5893                              <1> 		    ; (free inode search start value)
  5894                              <1> anyi_4:
  5895                              <1> 	; 12/03/2022
  5896                              <1> 	; increase free inode count
  5897 00004F78 8B5530              <1> 	mov	edx, [ebp+SB.FreeInodes]
  5898                              <1> 	;cmp	edx, 0FFFFFFFFh
  5899                              <1> 	;je	short anyi_5 ; invalid
  5900 00004F7B 42                  <1> 	inc	edx ; 0FFFFFFFFh -> 0
  5901 00004F7C 7403                <1> 	jz	short anyi_5 ; invalid
  5902 00004F7E 895530              <1> 	mov	[ebp+SB.FreeInodes], edx ; +1
  5903                              <1> anyi_5:
  5904 00004F81 E8E0130000          <1> 	call	get_system_time
  5905                              <1> 		; eax = current time (as unix epoch time)
  5906 00004F86 89455C              <1> 	mov	[ebp+SB.ModifTime], eax
  5907                              <1> 
  5908 00004F89 58                  <1> 	pop	eax ; *** ; inode number
  5909                              <1> 
  5910 00004F8A E861070000          <1> 	call	itrunc
  5911                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  5912                              <1> 
  5913                              <1> 	; 26/03/2022
  5914                              <1> 	; eax = 0 ; (itrunc clears eax at return)
  5915                              <1> 
  5916                              <1> 	; 12/03/2022
  5917                              <1> 	;pop	eax ; **** ; inode number
  5918                              <1> 
  5919                              <1> 	; 26/03/2022
  5920 00004F8F 66A3[58710000]      <1> 	mov	[i.flgs], ax ; (eax should be 0 here)
  5921                              <1> 	;mov 	word [i.flgs], 0
  5922                              <1> 		; clr i.flgs / clear all flags in the i-node
  5923 00004F95 C3                  <1> 	retn
  5924                              <1> 		; rts r0 / return
  5925                              <1> 
  5926                              <1> ;anyi_3: ; 1: / i-numbers match
  5927                              <1> ;	; 09/01/2022
  5928                              <1> ;	test	byte [ebx+5], 1 ; open for writing flag
  5929                              <1> ;	jz	short anyi_0	
  5930                              <1> ;
  5931                              <1> ;	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5932                              <1> ;	or	byte [ebx+5], 80h ; set deleted file flag (bit 7)
  5933                              <1> ;	; 22/06/2015
  5934                              <1> ;	;inc 	byte [ebx+9]
  5935                              <1> ;		; incb 7(r2) / increment upper byte of the 4th word
  5936                              <1> ;		   ; / in that fsp entry (deleted flag of fsp entry)
  5937                              <1> ;	retn
  5938                              <1> ;		; rts r0
  2089                                  %include 'u3.s'      ; 10/05/2015
  2090                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2091                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2092                              <1> ; ****************************************************************************
  2093                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2094                              <1> ; Last Modification: 24/12/2021
  2095                              <1> ; ----------------------------------------------------------------------------
  2096                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2097                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2098                              <1> ;
  2099                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2100                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2101                              <1> ; <Bell Laboratories (17/3/1972)>
  2102                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2103                              <1> ;
  2104                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2105                              <1> ;
  2106                              <1> ; ****************************************************************************
  2107                              <1> 
  2108                              <1> tswitch: ; Retro UNIX 386 v1
  2109                              <1> tswap:
  2110                              <1> 	; 01/09/2015
  2111                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2112                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2113                              <1> 	; time out swap, called when a user times out.
  2114                              <1> 	; the user is put on the low priority queue.
  2115                              <1> 	; This is done by making a link from the last user
  2116                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2117                              <1> 	; then he is swapped out.
  2118                              <1> 	;
  2119                              <1> 	; Retro UNIX 386 v1 modification ->
  2120                              <1> 	;       swap (software task switch) is performed by changing
  2121                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2122                              <1> 	;	as in Retro UNIX 8086 v1.
  2123                              <1> 	;
  2124                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2125                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2126                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2127                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2128                              <1> 	;	compatibles was using 1MB segmented memory 
  2129                              <1> 	;	in 8086/8088 times.
  2130                              <1> 	;
  2131                              <1> 	; INPUTS ->
  2132                              <1> 	;    u.uno - users process number
  2133                              <1> 	;    runq+4 - lowest priority queue
  2134                              <1> 	; OUTPUTS ->
  2135                              <1> 	;    r0 - users process number
  2136                              <1> 	;    r2 - lowest priority queue address
  2137                              <1> 	;
  2138                              <1> 	; ((AX = R0, BX = R2)) output
  2139                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2140                              <1> 	;
  2141 00004F96 A0[FD750000]        <1> 	mov 	al, [u.uno]
  2142                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2143                              <1> 		; mov  $runq+4,r2 
  2144                              <1> 			; / move lowest priority queue address to r2
  2145 00004F9B E8CD000000          <1>         call 	putlu
  2146                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2147                              <1> 		             ; / u.uno's user
  2148                              <1> 
  2149                              <1> switch: ; Retro UNIX 386 v1
  2150                              <1> swap:
  2151                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2152                              <1> 	; 02/09/2015
  2153                              <1> 	; 01/09/2015
  2154                              <1> 	; 31/08/2015
  2155                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2156                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2157                              <1> 	; 'swap' is routine that controls the swapping of processes
  2158                              <1> 	; in and out of core.
  2159                              <1> 	;
  2160                              <1> 	; Retro UNIX 386 v1 modification ->
  2161                              <1> 	;       swap (software task switch) is performed by changing
  2162                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2163                              <1> 	;	as in Retro UNIX 8086 v1.
  2164                              <1> 	;
  2165                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2166                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2167                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2168                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2169                              <1> 	;	compatibles was using 1MB segmented memory 
  2170                              <1> 	;	in 8086/8088 times.
  2171                              <1> 	;
  2172                              <1> 	; INPUTS ->
  2173                              <1> 	;    runq table - contains processes to run.
  2174                              <1> 	;    p.link - contains next process in line to be run.
  2175                              <1> 	;    u.uno - process number of process in core	
  2176                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2177                              <1> 	; OUTPUTS ->
  2178                              <1> 	;    (original unix v1 -> present process to its disk block)
  2179                              <1> 	;    (original unix v1 -> new process into core -> 
  2180                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2181                              <1> 	;	   for new process)
  2182                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2183                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2184                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2185                              <1> 	;	 for now, it will swap the process if there is not
  2186                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2187                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2188                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2189                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2190                              <1> 	;
  2191                              <1> 	;    u.pri -points to highest priority run Q.
  2192                              <1> 	;    r2 - points to the run queue.
  2193                              <1> 	;    r1 - contains new process number
  2194                              <1> 	;    r0 - points to place in routine or process that called
  2195                              <1> 	;	  swap all user parameters
  2196                              <1> 	;				
  2197                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2198                              <1> 	;
  2199                              <1> swap_0:
  2200                              <1> 		;mov $300,*$ps / processor priority = 6
  2201 00004FA0 BE[9C750000]        <1> 	mov	esi, runq
  2202                              <1> 		; mov $runq,r2 / r2 points to runq table
  2203                              <1> swap_1: ; 1: / search runq table for highest priority process
  2204 00004FA5 668B06              <1> 	mov	ax, [esi]
  2205 00004FA8 6621C0              <1> 	and 	ax, ax
  2206                              <1>        		; tst (r2)+ / are there any processes to run 
  2207                              <1> 			  ; / in this Q entry
  2208 00004FAB 7507                <1> 	jnz	short swap_2
  2209                              <1>        		; bne 1f / yes, process 1f
  2210                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2211                              <1> 			       ; / to end of table
  2212                              <1> 		; bne 1b / if not at end, go back
  2213 00004FAD E8E0000000          <1> 	call	idle
  2214                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2215                              <1> 				       ; / all queues are empty
  2216 00004FB2 EBF1                <1> 	jmp	short swap_1
  2217                              <1> 		; br swap
  2218                              <1> swap_2: ; 1:
  2219 00004FB4 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2220                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2221                              <1>  		; mov r2,u.pri / set present user to this run queue
  2222                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2223 00004FB7 38E0                <1> 	cmp	al, ah
  2224                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2225                              <1> 			      ; / in this Q to be run
  2226 00004FB9 740A                <1> 	je	short swap_3
  2227                              <1>        		; beq 1f / yes
  2228                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2229                              <1> 	;movzx	ebx, al
  2230 00004FBB 8AA3[E7710000]      <1> 	mov	ah, [ebx+p.link-1] 
  2231 00004FC1 8826                <1>        	mov	[esi], ah
  2232                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2233                              <1> 				       ; / in line into run queue
  2234 00004FC3 EB05                <1> 	jmp	short swap_4
  2235                              <1>        		; br 2f
  2236                              <1> swap_3: ; 1:
  2237                              <1> 	;xor	dx, dx
  2238                              <1> 	; 24/12/2021
  2239 00004FC5 31D2                <1> 	xor	edx, edx
  2240 00004FC7 668916              <1> 	mov	[esi], dx
  2241                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2242                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2243                              <1>       ; / in new process if required
  2244                              <1>        		; clr *$ps / clear processor status
  2245 00004FCA 8A25[FD750000]      <1> 	mov 	ah, [u.uno]
  2246 00004FD0 38C4                <1> 	cmp	ah, al
  2247                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2248                              <1> 			      ; / the process in core?
  2249 00004FD2 743B                <1>        	je	short swap_8
  2250                              <1>        		; beq 2f / yes, don't have to swap
  2251                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2252                              <1> 			   ; / (address in routine that called swap)
  2253                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2254                              <1> 	; 01/09/2015
  2255                              <1> 	;mov	[u.usp], esp
  2256                              <1>        		; mov sp,u.usp / save stack pointer
  2257                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2258                              <1> 			       ; / to the stack pointer
  2259 00004FD4 08E4                <1> 	or	ah, ah
  2260                              <1>        		; tstb u.uno / is the process # = 0
  2261 00004FD6 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2262                              <1> 		; beq  1f / yes, kill process by overwriting
  2263                              <1> 	; 02/09/2015
  2264 00004FD8 8925[A8750000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2265                              <1> 	;
  2266 00004FDE E834000000          <1> 	call	wswap
  2267                              <1> 		;jsr r0,wswap / write out core to disk
  2268                              <1> 	 ; 31/08/2015
  2269                              <1> 	;movzx	ebx, al ; New (running) process number
  2270 00004FE3 EB1C                <1> 	jmp 	short swap_7
  2271                              <1> swap_6:
  2272                              <1> 	; 31/08/2015
  2273                              <1> 	; Deallocate memory pages belong to the process
  2274                              <1> 	; which is being terminated
  2275                              <1> 	; 14/05/2015 ('sysexit')
  2276                              <1>  	; Deallocate memory pages of the process
  2277                              <1> 	; (Retro UNIX 386 v1 modification !)
  2278                              <1> 	;
  2279                              <1> 	; movzx ebx, al
  2280 00004FE5 53                  <1> 	push	ebx
  2281 00004FE6 A1[0C760000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2282 00004FEB 8B1D[10760000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2283 00004FF1 E8EEDEFFFF          <1> 	call	deallocate_page_dir
  2284 00004FF6 A1[08760000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2285 00004FFB E87CDFFFFF          <1> 	call	deallocate_page
  2286 00005000 5B                  <1> 	pop	ebx
  2287                              <1> swap_7: ;1: 
  2288                              <1> 	; 02/09/2015
  2289                              <1> 	; 31/08/2015
  2290                              <1> 	; 14/05/2015
  2291 00005001 C0E302              <1> 	shl	bl, 2 ; * 4 
  2292 00005004 8B83[04720000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2293                              <1> 	;cli
  2294 0000500A E831000000          <1> 	call	rswap
  2295                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2296                              <1> 		; jsr r0,rswap / read new process into core
  2297                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2298                              <1> 			      ; / to his program to its normal
  2299                              <1> 	; 01/09/2015
  2300                              <1> 	;mov	esp, [u.usp]	
  2301                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2302                              <1> 			     ; / new process stack
  2303                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2304                              <1> 			     ; / that just got swapped in, left off.,
  2305                              <1> 			     ; / i.e., transfer control to new process
  2306                              <1> 	;sti
  2307                              <1> swap_8: ;2:
  2308                              <1> 	; RETRO UNIX 8086 v1 modification !
  2309 0000500F C605[F4750000]04    <1> 	mov	byte [u.quant], time_count 
  2310                              <1> 		; movb $30.,uquant / initialize process time quantum
  2311 00005016 C3                  <1> 	retn
  2312                              <1> 		; rts r0 / return
  2313                              <1> 
  2314                              <1> wswap:  ; < swap out, swap to disk >
  2315                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2316                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2317                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2318                              <1> 	; appropriate disk area.
  2319                              <1> 	;
  2320                              <1> 	; Retro UNIX 386 v1 modification ->
  2321                              <1> 	;       User (u) structure content and the user's register content
  2322                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2323                              <1> 	;	saving 'u' structure and user registers for task switching).
  2324                              <1> 	;	u.usp - points to kernel stack address which contains
  2325                              <1> 	;		user's registers while entering system call.  
  2326                              <1> 	;	u.sp  - points to kernel stack address 
  2327                              <1> 	;		to return from system call -for IRET-.
  2328                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2329                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2330                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2331                              <1> 	;
  2332                              <1> 	; Retro UNIX 8086 v1 modification ->
  2333                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2334                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2335                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2336                              <1> 	;	compatibles was using 1MB segmented memory 
  2337                              <1> 	;	in 8086/8088 times.
  2338                              <1> 	;
  2339                              <1> 	; INPUTS ->
  2340                              <1> 	;    u.break - points to end of program
  2341                              <1> 	;    u.usp - stack pointer at the moment of swap
  2342                              <1> 	;    core - beginning of process program		
  2343                              <1> 	;    ecore - end of core 	
  2344                              <1> 	;    user - start of user parameter area		
  2345                              <1> 	;    u.uno - user process number	
  2346                              <1> 	;    p.dska - holds block number of process	
  2347                              <1> 	; OUTPUTS ->
  2348                              <1> 	;    swp I/O queue
  2349                              <1> 	;    p.break - negative word count of process 
  2350                              <1> 	;    r1 - process disk address	
  2351                              <1> 	;    r2 - negative word count
  2352                              <1> 	;
  2353                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2354                              <1> 	;
  2355                              <1> 	; INPUTS ->
  2356                              <1> 	;    u.uno - process number (to be swapped out)
  2357                              <1> 	; OUTPUTS ->
  2358                              <1> 	;    none
  2359                              <1> 	;
  2360                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2361                              <1> 	;
  2362 00005017 8B3D[08760000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2363 0000501D B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2364 00005022 BE[A4750000]        <1> 	mov	esi, user ; active user (u) structure	
  2365 00005027 F3A5                <1> 	rep	movsd
  2366                              <1> 	;
  2367 00005029 8B35[A8750000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2368                              <1> 			     ;      points to user registers)
  2369 0000502F 8B0D[A4750000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2370                              <1> 			     ; (for IRET)
  2371                              <1> 			     ; [u.sp] -> EIP (user)
  2372                              <1> 			     ; [u.sp+4]-> CS (user)
  2373                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2374                              <1> 			     ; [u.sp+12] -> ESP (user)
  2375                              <1> 			     ; [u.sp+16] -> SS (user)	
  2376 00005035 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2377 00005037 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2378                              <1> 			     ; (for IRET) 	
  2379 0000503A C1E902              <1> 	shr	ecx, 2	     		
  2380 0000503D F3A5                <1> 	rep	movsd
  2381 0000503F C3                  <1> 	retn
  2382                              <1> 
  2383                              <1> 	; Original UNIX v1 'wswap' routine:
  2384                              <1> 	; wswap:
  2385                              <1> 		; mov *$30,u.emt / determines handling of emts
  2386                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2387                              <1> 				; / illegal instructions
  2388                              <1> 		; mov u.break,r2 / put process program break address in r2
  2389                              <1> 		; inc r2 / add 1 to it 
  2390                              <1> 		; bic $1,r2 / make it even
  2391                              <1> 		; mov r2,u.break / set break to an even location
  2392                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2393                              <1> 			     ; / at moment of swap in r3
  2394                              <1> 		; cmp r2,$core / is u.break less than $core
  2395                              <1> 		; blos 2f / yes
  2396                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2397                              <1>        		; bhis 2f / yes
  2398                              <1> 	; 1:
  2399                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2400                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2401                              <1> 		; bne 1b / no, keep packing
  2402                              <1> 	 	; br 1f / yes
  2403                              <1> 	; 2:
  2404                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2405                              <1> 	; 1:
  2406                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2407                              <1> 			   ; / (user up to end of stack gets written out)
  2408                              <1> 		; neg r2 / make it negative
  2409                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2410                              <1> 		; mov r2,swp+4 / word count
  2411                              <1> 		; movb u.uno,r1 / move user process number to r1
  2412                              <1> 		; asl r1 / x2 for index
  2413                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2414                              <1> 				     ; / into the p.break table
  2415                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2416                              <1> 				    ; /	for process to r1
  2417                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2418                              <1> 			     ; / (block number)
  2419                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2420                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2421                              <1> 	; 1:
  2422                              <1>        		; tstb swp+1 / is lt done writing?
  2423                              <1>        		; bne 1b / no, wait
  2424                              <1> 		; rts r0 / yes, return to swap
  2425                              <1> 
  2426                              <1> rswap:  ; < swap in, swap from disk >
  2427                              <1> 	; 15/09/2015
  2428                              <1> 	; 28/08/2015
  2429                              <1> 	; 14/05/2015
  2430                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2431                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2432                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2433                              <1> 	; from disk into core.
  2434                              <1> 	;
  2435                              <1> 	; Retro UNIX 386 v1 modification ->
  2436                              <1> 	;       User (u) structure content and the user's register content
  2437                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2438                              <1> 	;	saving 'u' structure and user registers for task switching).
  2439                              <1> 	;	u.usp - points to kernel stack address which contains
  2440                              <1> 	;		user's registers while entering system call.  
  2441                              <1> 	;	u.sp  - points to kernel stack address 
  2442                              <1> 	;		to return from system call -for IRET-.
  2443                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2444                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2445                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2446                              <1> 	;
  2447                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2448                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2449                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2450                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2451                              <1> 	;	compatibles was using 1MB segmented memory 
  2452                              <1> 	;	in 8086/8088 times.
  2453                              <1> 	;
  2454                              <1> 	; INPUTS ->
  2455                              <1> 	;    r1 - process number of process to be read in
  2456                              <1> 	;    p.break - negative of word count of process 
  2457                              <1> 	;    p.dska - disk address of the process		
  2458                              <1> 	;    u.emt - determines handling of emt's 	
  2459                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2460                              <1> 	; OUTPUTS ->
  2461                              <1> 	;    8 = (u.ilgins)
  2462                              <1> 	;    24 = (u.emt)
  2463                              <1> 	;    swp - bit 10 is set to indicate read 
  2464                              <1> 	;		(bit 15=0 when reading is done)	
  2465                              <1> 	;    swp+2 - disk block address
  2466                              <1> 	;    swp+4 - negative word count 	
  2467                              <1> 	;      ((swp+6 - address of user structure)) 
  2468                              <1> 	;
  2469                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2470                              <1> 	;
  2471                              <1> 	; INPUTS ->
  2472                              <1> 	;    AL	- new process number (to be swapped in)	 
  2473                              <1> 	; OUTPUTS ->
  2474                              <1> 	;    none
  2475                              <1> 	;
  2476                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2477                              <1> 	;
  2478                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2479 00005040 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2480 00005042 B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2481 00005047 BF[A4750000]        <1> 	mov	edi, user ; active user (u) structure	
  2482 0000504C F3A5                <1> 	rep	movsd
  2483 0000504E 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2484 0000504F 8B3D[A8750000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2485                              <1> 			     ;      points to user registers)
  2486 00005055 8B0D[A4750000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2487                              <1> 			     ; (for IRET)
  2488                              <1> 			     ; [u.sp] -> EIP (user)
  2489                              <1> 			     ; [u.sp+4]-> CS (user)
  2490                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2491                              <1> 			     ; [u.sp+12] -> ESP (user)
  2492                              <1> 			     ; [u.sp+16] -> SS (user)		
  2493                              <1> 	; 28/08/2015
  2494 0000505B 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2495 0000505D 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2496                              <1> 			     ; (for IRET) 	
  2497 00005060 C1E902              <1> 	shr	ecx, 2	       		
  2498 00005063 F3A5                <1> 	rep	movsd
  2499 00005065 8B25[A8750000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2500 0000506B 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2501 0000506C C3                  <1> 	retn
  2502                              <1> 
  2503                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2504                              <1> 	;rswap:
  2505                              <1>        		; asl r1 / process number x2 for index
  2506                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2507                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2508                              <1>        		; bis $2000,swp / read
  2509                              <1>        		; jsr r0,ppoke / read it in 
  2510                              <1> 	; 1:
  2511                              <1>        		; tstb swp+1 / done
  2512                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2513                              <1>        		; mov u.emt,*$30 / yes move these
  2514                              <1>        		; mov u.ilgins,*$10 / back
  2515                              <1>        		; rts r0 / return
  2516                              <1> 
  2517                              <1> 	;unpack: ; / move stack back to its normal place
  2518                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2519                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2520                              <1> 		; blos 2f / yes, return
  2521                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2522                              <1> 			     ; / before swapping
  2523                              <1> 		; bhis 2f / yes, return
  2524                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2525                              <1> 		; add r3,r2
  2526                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2527                              <1> 	; 1:
  2528                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2529                              <1> 		; cmp r2,u.break / in core
  2530                              <1> 		; bne 1b
  2531                              <1> 	; 2:
  2532                              <1>        		; rts r0
  2533                              <1> 
  2534                              <1> putlu: 
  2535                              <1> 	; 12/09/2015
  2536                              <1> 	; 02/09/2015
  2537                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2538                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2539                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2540                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2541                              <1> 	; the last process on the queue to process in r1 by putting
  2542                              <1> 	; the process number in r1 into the last process's link.
  2543                              <1> 	;
  2544                              <1> 	; INPUTS ->
  2545                              <1> 	;    r1 - user process number
  2546                              <1> 	;    r2 - points to lowest priority queue 
  2547                              <1> 	;    p.dska - disk address of the process		
  2548                              <1> 	;    u.emt - determines handling of emt's 	
  2549                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2550                              <1> 	; OUTPUTS ->
  2551                              <1> 	;    r3 - process number of last process on the queue upon
  2552                              <1> 	;	  entering putlu
  2553                              <1> 	;    p.link-1 + r3 - process number in r1
  2554                              <1> 	;    r2 - points to lowest priority queue
  2555                              <1> 	;
  2556                              <1> 	; ((Modified registers: EDX, EBX)) 
  2557                              <1> 	;
  2558                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2559                              <1> 
  2560                              <1> 	; eBX = r2
  2561                              <1> 	; eAX = r1 (AL=r1b)
  2562                              <1> 
  2563 0000506D BB[9C750000]        <1> 	mov	ebx, runq
  2564 00005072 0FB613              <1> 	movzx  	edx, byte [ebx]
  2565 00005075 43                  <1> 	inc	ebx
  2566 00005076 20D2                <1> 	and	dl, dl
  2567                              <1> 		; tstb (r2)+ / is queue empty?
  2568 00005078 740A                <1>        	jz	short putlu_1
  2569                              <1> 		; beq 1f / yes, branch
  2570 0000507A 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2571                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2572                              <1> 			     ; / in r3
  2573 0000507C 8882[E7710000]      <1>        	mov	[edx+p.link-1], al
  2574                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2575                              <1> 			     ; / "last users" link
  2576 00005082 EB03                <1> 	jmp	short putlu_2
  2577                              <1> 		; br 2f /
  2578                              <1> putlu_1: ; 1:
  2579 00005084 8843FF              <1> 	mov	[ebx-1], al
  2580                              <1>        		; movb r1,-1(r2) / user is only user; 
  2581                              <1> 			    ; / put process no. at beginning and at end
  2582                              <1> putlu_2: ; 2: 
  2583 00005087 8803                <1> 	mov	[ebx], al
  2584                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2585                              <1> 			     ; / on the queue
  2586 00005089 88C2                <1> 	mov	dl, al
  2587 0000508B 88B2[E7710000]      <1>         mov     [edx+p.link-1], dh ; 0
  2588                              <1> 		; dec r2 / restore r2
  2589 00005091 C3                  <1>         retn
  2590                              <1> 		; rts r0
  2591                              <1> 
  2592                              <1> ;copyz:
  2593                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2594                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2595                              <1> ;       mov     (r0)+,r1
  2596                              <1> ;       mov     (r0)+,r2
  2597                              <1> ;1:
  2598                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2599                              <1> ;       cmp     r1,r2 
  2600                              <1> ;       blo     1b
  2601                              <1> ;       mov     (sp)+,r2 / restore r2
  2602                              <1> ;       mov     (sp)+,r1 / restore r1
  2603                              <1> ;       rts     r0 
  2604                              <1> 
  2605                              <1> idle:
  2606                              <1> 	; 01/09/2015
  2607                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2608                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2609                              <1> 	; (idle & wait loop)
  2610                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2611                              <1> 	; idle procedure!
  2612                              <1>       	;
  2613                              <1>   	; 01/09/2015
  2614 00005092 FB                  <1> 	sti
  2615                              <1>       	; 29/07/2013
  2616 00005093 F4                  <1>       	hlt
  2617 00005094 90                  <1>       	nop ; 10/10/2013
  2618 00005095 90                  <1>       	nop
  2619 00005096 90                  <1>       	nop
  2620                              <1>       	; 23/10/2013
  2621 00005097 90                  <1>       	nop
  2622 00005098 90                  <1>       	nop
  2623 00005099 90                  <1>       	nop
  2624 0000509A 90                  <1>       	nop
  2625 0000509B C3                  <1>       	retn      
  2626                              <1> 
  2627                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2628                              <1> 	;clr *$ps / clear ps
  2629                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2630                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2631                              <1> 	;1 / wait for interrupt
  2632                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2633                              <1> 	;mov (sp)+,*$ps
  2634                              <1> 	;rts r0
  2635                              <1> 
  2636                              <1> clear:
  2637                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2638                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2639                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2640                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2641                              <1> 	; on the current device (cdev)
  2642                              <1> 	;	
  2643                              <1> 	; INPUTS ->
  2644                              <1> 	;    r1 - block number of block to be zeroed
  2645                              <1> 	;    cdev - current device number 
  2646                              <1> 	; OUTPUTS ->
  2647                              <1> 	;    a zeroed I/O buffer onto the current device
  2648                              <1> 	;    r1 - points to last entry in the I/O buffer
  2649                              <1> 	;
  2650                              <1> 	; ((AX = R1)) input/output
  2651                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2652                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2653                              <1> 
  2654 0000509C E8E1110000          <1> 	call 	wslot
  2655                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2656                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2657 000050A1 89DF                <1> 	mov	edi, ebx ; r5
  2658 000050A3 89C2                <1> 	mov	edx, eax
  2659 000050A5 B980000000          <1> 	mov	ecx, 128
  2660                              <1> 		; mov $256.,r3
  2661 000050AA 31C0                <1> 	xor	eax, eax
  2662 000050AC F3AB                <1> 	rep	stosd
  2663 000050AE 89D0                <1> 	mov	eax, edx
  2664                              <1> ; 1: 
  2665                              <1>        		; clr (r5)+ / zero data word in buffer
  2666                              <1>        		; dec r3
  2667                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2668                              <1> 	;call	dskwr
  2669                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2670                              <1>                              ; / block specified in r1
  2671                              <1> 	; eAX (r1) = block number
  2672                              <1> 	;retn
  2673                              <1> 		; rts r0
  2674                              <1> 	; 24/12/2021
  2675 000050B0 E9E9110000          <1> 	jmp	dskwr
  2090                                  %include 'u4.s'      ; 15/04/2015
  2091                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2092                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2093                              <1> ; ****************************************************************************
  2094                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2095                              <1> ; Last Modification: 27/02/2022 (Retro UNIX 386 v1.2)
  2096                              <1> ; ----------------------------------------------------------------------------
  2097                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2098                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2099                              <1> ;
  2100                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2101                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2102                              <1> ; <Bell Laboratories (17/3/1972)>
  2103                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2104                              <1> ;
  2105                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2106                              <1> ;
  2107                              <1> ; ****************************************************************************
  2108                              <1> 
  2109                              <1> ;setisp:
  2110                              <1>        ;mov     r1,-(sp)
  2111                              <1>        ;mov     r2,-(sp)
  2112                              <1>        ;mov     r3,-(sp)
  2113                              <1>        ;mov     clockp,-(sp)
  2114                              <1>        ;mov     $s.syst+2,clockp
  2115                              <1>        ;jmp     (r0)
  2116                              <1> 
  2117                              <1> clock: ; / interrupt from 60 cycle clock
  2118                              <1> 	
  2119                              <1> 	; 14/10/2015
  2120                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2121                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2122                              <1> 
  2123                              <1>        ;mov     r0,-(sp) / save r0
  2124                              <1>        ;tst     *$lks / restart clock?
  2125                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2126                              <1>        ;inc     (r0)
  2127                              <1>        ;bne     1f
  2128                              <1>        ;inc     -(r0)
  2129                              <1> ;1:
  2130                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2131                              <1>        ;inc     (r0)
  2132                              <1>        ;bne     1f
  2133                              <1>        ;inc     -(r0)
  2134                              <1> ;1:
  2135                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2136                              <1> 
  2137 000050B5 803D[F4750000]00    <1> 	cmp	byte [u.quant], 0
  2138 000050BC 772C                <1> 	ja	short clk_1
  2139                              <1> 	;
  2140 000050BE 803D[A2750000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2141 000050C5 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2142 000050C7 803D[FD750000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2143 000050CE 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2144 000050D0 66833D[F8750000]00  <1> 	cmp	word [u.intr], 0
  2145 000050D8 7616                <1> 	jna	short clk_2
  2146                              <1> clk_0:
  2147                              <1> 	; 14/10/2015
  2148 000050DA FE05[A2750000]      <1> 	inc	byte [sysflg] ; Now, we are in system space
  2149 000050E0 58                  <1> 	pop	eax ; return address to the timer interrupt
  2150                              <1> 	;
  2151 000050E1 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2152                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2153 000050E3 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2154                              <1> 	;
  2155 000050E5 E9E3EAFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2156                              <1> clk_1:
  2157 000050EA FE0D[F4750000]      <1> 	dec	byte [u.quant]
  2158                              <1> clk_2:
  2159 000050F0 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2160                              <1> 
  2161                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2162                              <1> 
  2163                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2164                              <1>        ;decb    (r0)
  2165                              <1>        ;bge     1f / if less than 0
  2166                              <1>        ;clrb    (r0) / make it 0
  2167                              <1> ;1: / decrement time out counts return now if priority was not 0
  2168                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2169                              <1>        ;bge     2f / yes, check time outs
  2170                              <1>        ;tstb    (r0) / no, user timed out?
  2171                              <1>        ;bne     1f / no
  2172                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2173                              <1>        ;bne     1f / no, 1f
  2174                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2175                              <1>        ;sys     0 / sysrele
  2176                              <1>        ;rti
  2177                              <1> ;2: / priority is high so just decrement time out counts
  2178                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2179                              <1> ;2:
  2180                              <1>        ;tstb    (r0) / is the time out?
  2181                              <1>        ;beq     3f / yes, 3f (get next entry)
  2182                              <1>        ;decb    (r0) / no, decrement the time
  2183                              <1>        ;bne     3f / isit zero now?
  2184                              <1>        ;incb    (r0) / yes, increment the time
  2185                              <1> ;3:
  2186                              <1>        ;inc     r0 / next entry
  2187                              <1>        ;cmp     r0,$touts / end of toutt table?
  2188                              <1>        ;blo     2b / no, check this entry
  2189                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2190                              <1>        ;rti / return from interrupt
  2191                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2192                              <1>        ;mov     (sp)+,r0 / restore r0
  2193                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2194                              <1>        ;jsr     r0,setisp / save registers
  2195                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2196                              <1>                                ;  / the table
  2197                              <1> ;1:
  2198                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2199                              <1>        ;beq     2f / yes
  2200                              <1>        ;decb    toutt(r0) / no, decrement the time
  2201                              <1>        ;bne     2f / is the time 0, now
  2202                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2203                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2204                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2205                              <1> ;2:
  2206                              <1>        ;dec     r0 / set up r0 for next entry
  2207                              <1>        ;bge     1b / finished? , no, go back
  2208                              <1>        ;br      retisp / yes, restore registers and do a rti
  2209                              <1> 
  2210                              <1> ;retisp:
  2211                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2212                              <1>        ;mov     (sp)+,r3
  2213                              <1>        ;mov     (sp)+,r2
  2214                              <1>        ;mov     (sp)+,r1
  2215                              <1>        ;mov     (sp)+,r0
  2216                              <1>        ;rti     / return from interrupt
  2217                              <1> 
  2218                              <1> 
  2219                              <1> wakeup: ; / wakeup processes waiting for an event 
  2220                              <1> 	; / by linking them to the queue
  2221                              <1> 	;
  2222                              <1> 	; 27/02/2022
  2223                              <1> 	; 15/09/2015
  2224                              <1> 	; 29/06/2015
  2225                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2226                              <1> 	;
  2227                              <1> 	; 15/05/2013 - 02/06/2014
  2228                              <1> 	; Retro UNIX 8086 v1 modification !
  2229                              <1> 	; (Process/task switching routine by using
  2230                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2231                              <1> 	;
  2232                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2233                              <1> 	; sleeping in the specified wait channel by creating a link 
  2234                              <1> 	; to it from the last user process on the run queue.
  2235                              <1> 	; If there is no process to wake up, nothing happens.
  2236                              <1> 	;
  2237                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2238                              <1> 	; 'switching' status of the current process (owns current tty)
  2239                              <1> 	; (via alt + function keys) to a process which has highest
  2240                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2241                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2242                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2243                              <1> 	; tty for tty switching by keyboard.)	 
  2244                              <1> 	; 
  2245                              <1> 	; INPUT -> 
  2246                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2247                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2248                              <1> 	;
  2249                              <1> 	; ((modified registers: EAX, EBX))
  2250                              <1> 	;
  2251 000050F1 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2252 000050F4 81C3[F8700000]      <1> 	add	ebx, wlist
  2253 000050FA 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2254 000050FC 20C0                <1> 	and	al, al
  2255 000050FE 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2256                              <1> 	;
  2257 00005100 30E4                <1> 	xor	ah, ah
  2258 00005102 8825[F4750000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2259 00005108 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2260                              <1> 	; 15/09/2015
  2261 0000510A 0FB6D8              <1> 	movzx	ebx, al
  2262                              <1> 	; 27/02/2022 (p.waitc is not used)
  2263                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2264 0000510D FEC4                <1> 	inc	ah
  2265 0000510F 88A3[F7710000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2266                              <1> 	;
  2267 00005115 57                  <1> 	push	edi
  2268 00005116 52                  <1> 	push	edx
  2269 00005117 E851FFFFFF          <1> 	call	putlu
  2270 0000511C 5A                  <1> 	pop	edx
  2271 0000511D 5F                  <1> 	pop	edi
  2272                              <1> wa0:
  2273 0000511E C3                  <1> 	retn
  2274                              <1> 
  2275                              <1> 	; 27/02/2022
  2276                              <1> 	; 05/12/2021
  2277                              <1> 	; 30/11/2021 - Retro UNIX 386 v1.2
  2278                              <1> sleep: 
  2279                              <1> 	; 15/09/2015
  2280                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2281                              <1> 	;
  2282                              <1> 	; 09/05/2013 - 20/03/2014
  2283                              <1> 	;
  2284                              <1> 	; Retro UNIX 8086 v1 modification !
  2285                              <1> 	; (Process/task switching and quit routine by using
  2286                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2287                              <1> 	;
  2288                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2289                              <1> 	; tty and tape output or input becomes available
  2290                              <1> 	; and process is put on waiting channel and swapped out,
  2291                              <1> 	; then -when the tty or tape is ready to write or read-
  2292                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2293                              <1> 	;
  2294                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2295                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2296                              <1> 	; status of the current process also INT 1Ch will count down
  2297                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2298                              <1> 	; to tty buffer of the current process and kernel will get
  2299                              <1> 	; user input by using tty buffer of the current process
  2300                              <1> 	; (instead of standard INT 16h interrupt).
  2301                              <1> 	; TTY output will be redirected to related video page of text mode
  2302                              <1> 	; (INT 10h will be called with different video page depending
  2303                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2304                              <1> 	; pseudo screens.)
  2305                              <1> 	;
  2306                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2307                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2308                              <1> 	; characters/data on serial port(s).
  2309                              <1> 	;
  2310                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2311                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2312                              <1> 	; 
  2313                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2314                              <1> 	;
  2315                              <1> 	;; 05/10/2013
  2316                              <1>         ;10/12/2013
  2317                              <1> 	;cmp   byte [u.uno], 1
  2318                              <1>         ;ja    short sleep0
  2319                              <1> 	;retn
  2320                              <1> 
  2321                              <1> 	; 20/03/2014
  2322                              <1> 	;mov	bx, [runq]
  2323                              <1> 	;cmp	bl, bh
  2324                              <1> 	;jne	short sleep0	
  2325                              <1> 	; 25/02/2014
  2326                              <1> 	;cmp	word ptr [runq], 0
  2327                              <1> 	;ja	short sleep0	
  2328                              <1> 	;retn
  2329                              <1> sleep0:
  2330                              <1> 	;
  2331 0000511F E849000000          <1> 	call	isintr
  2332                              <1> 	;jnz	sysret
  2333                              <1> 		; / wait for event
  2334                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2335                              <1> 			      ; / or quit from user
  2336                              <1>                		; br 2f / something happened
  2337                              <1> 			      ; / yes, his interrupt so return
  2338                              <1>                      	      ;	/ to user
  2339                              <1> 	; 05/12/2021
  2340 00005124 7405                <1> 	jz	short sleep_2
  2341                              <1> sleep_3:
  2342 00005126 E93DEAFFFF          <1> 	jmp	sysret
  2343                              <1> sleep_2:
  2344                              <1> 	; 30/06/2015
  2345 0000512B 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2346 0000512E 81C3[F8700000]      <1> 	add	ebx, wlist
  2347 00005134 8A03                <1> 	mov	al, [ebx]
  2348 00005136 20C0                <1> 	and	al, al
  2349 00005138 7407                <1> 	jz	short sleep1
  2350 0000513A 53                  <1> 	push	ebx
  2351 0000513B E82DFFFFFF          <1> 	call	putlu
  2352 00005140 5B                  <1> 	pop	ebx
  2353                              <1> sleep1:
  2354 00005141 A0[FD750000]        <1> 	mov	al, [u.uno]    
  2355 00005146 8803                <1>   	mov	[ebx], al 	; put the process number
  2356                              <1> 				; in the wait channel
  2357                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2358                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2359                              <1> 				     ; / on the stack
  2360                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2361                              <1> 				     ; / to put to sleep in there
  2362                              <1> 	; 30/11/2021
  2363 00005148 31DB                <1> 	xor	ebx, ebx
  2364 0000514A 8A1D[8D750000]      <1> 	mov	bl, [cdev]
  2365 00005150 53                  <1> 	push	ebx
  2366                              <1>         ; 15/09/2015
  2367                              <1> 	;movzx	ebx, al
  2368 00005151 88C3                <1> 	mov	bl, al
  2369 00005153 C683[F7710000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2370                              <1> 	; 27/02/2022 (p.waitc is not used)
  2371                              <1> 	;inc	ah
  2372                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2373                              <1> 	;
  2374                              <1> 	;
  2375                              <1> 	;push	word [cdev]
  2376                              <1> 	;	; mov cdev,-(sp) / nothing happened in isintr so
  2377 0000515A E841FEFFFF          <1> 	call	swap
  2378                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2379                              <1>         ;pop	word [cdev]
  2380                              <1> 	;	; mov (sp)+,cdev / restore device
  2381                              <1> 	; 30/11/2021
  2382 0000515F 58                  <1> 	pop	eax
  2383 00005160 A2[8D750000]        <1> 	mov	[cdev], al
  2384 00005165 E803000000          <1> 	call	isintr
  2385                              <1> 	; 22/09/2013
  2386                              <1> 	;jnz	sysret         
  2387                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2388                              <1>                		; br 2f / yes, return to new user
  2389                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2390                              <1> 				; / originally on the wait channel
  2391                              <1>        		; beq 1f / if 0 branch
  2392                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2393                              <1>        		; mov $300,*$ps / processor priority = 6
  2394                              <1> 		; jsr r0,putlu / create link to old process number
  2395                              <1>        		; clr *$ps / clear the status; process priority = 0
  2396                              <1> 	; 05/12/2021
  2397 0000516A 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2398                              <1>      ;1:
  2399 0000516C C3                  <1> 	retn
  2400                              <1> 		; rts r0 / return
  2401                              <1>      ;2:
  2402                              <1>         ;;jmp	sysret
  2403                              <1> 		; jmp sysret / return to user
  2404                              <1> 
  2405                              <1> isintr:
  2406                              <1> 	; 30/11/2021	
  2407                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2408                              <1> 	;
  2409                              <1> 	; 09/05/2013 - 30/05/2014
  2410                              <1> 	;
  2411                              <1> 	; Retro UNIX 8086 v1 modification !
  2412                              <1> 	; (Process/task switching and quit routine by using
  2413                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2414                              <1> 	;
  2415                              <1> 	; Retro UNIX 8086 v1 modification:
  2416                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2417                              <1> 	;  and there is a 'quit' request by user;
  2418                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2419                              <1> 	;  "nothing to do". (20/10/2013)
  2420                              <1> 	;
  2421                              <1> 	; 20/10/2013
  2422 0000516D 66833D[E2750000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2423 00005175 761F                <1> 	jna	short isintr2 ; retn
  2424                              <1> 	; 03/09/2013
  2425                              <1> 	; (nothing to do)
  2426                              <1> 	;retn
  2427                              <1> 	; 22/09/2013
  2428 00005177 66833D[F8750000]00  <1> 	cmp	word [u.intr], 0
  2429 0000517F 7615                <1> 	jna	short isintr2 ; retn
  2430                              <1> 	; 30/05/2014
  2431                              <1> 	;push	ax
  2432 00005181 50                  <1> 	push	eax ; 30/11/2021 
  2433 00005182 66A1[FA750000]      <1> 	mov	ax, [u.quit]
  2434 00005188 6609C0              <1> 	or	ax, ax ; 0 ?
  2435 0000518B 7408                <1> 	jz	short isintr1 ; zf = 1
  2436 0000518D 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2437 00005191 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2438                              <1> 	;xor	ax, ax ; zf = 1
  2439                              <1> 	; 30/11/2021
  2440 00005193 31C0                <1> 	xor	eax, eax
  2441                              <1> isintr1:
  2442                              <1> 	;pop	ax
  2443                              <1> 	; 30/11/2021
  2444 00005195 58                  <1> 	pop	eax
  2445                              <1> isintr2: ; 22/09/2013
  2446                              <1> 	; zf=1 -> nothing to do
  2447 00005196 C3                  <1> 	retn
  2448                              <1> 
  2449                              <1> 	; UNIX v1 original 'isintr' routine... 
  2450                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2451                              <1>        	;mov     r2,-(sp) / save r2
  2452                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2453                              <1>         ;                 / typewriter
  2454                              <1>        	;beq     1f / if 0, do nothing except skip return
  2455                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2456                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2457                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2458                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2459                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2460                              <1>         ;              / of interrupts
  2461                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2462                              <1>      ;1:
  2463                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2464                              <1>      ;4:
  2465                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2466                              <1>        	;mov     (sp)+,r1
  2467                              <1>        	;rts     r0
  2468                              <1>      ;3: / interrupt char = quit (fs)
  2469                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2470                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2471                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2472                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2473                              <1>      ;1: / find process control tty entry in tty block
  2474                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2475                              <1>        	;beq     1f / block found go to 1f
  2476                              <1>        	;add     $8,r1 / look at next tty block
  2477                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2478                              <1>        	;blo     1b / no
  2479                              <1>        	;br      4b / no process control tty found so go to 4b
  2480                              <1>      ;1:
  2481                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2482                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2483                              <1>         ;                  / identifier
  2484                              <1>        	;inc     0f / increment
  2485                              <1>      ;1:
  2486                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2487                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2488                              <1>         ;             / being typed out after you hit the interrupt
  2489                              <1>         ;             / key
  2490                              <1>        	;br      1b
  2091                                  %include 'u5.s'      ; 03/06/2015
  2092                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2093                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2094                              <1> ; ****************************************************************************
  2095                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2096                              <1> ; Last Modification: 26/03/2022
  2097                              <1> ; ----------------------------------------------------------------------------
  2098                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2099                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2100                              <1> ;
  2101                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2102                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2103                              <1> ; <Bell Laboratories (17/3/1972)>
  2104                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2105                              <1> ;
  2106                              <1> ; Retro UNIX 8086 v1 - U5.AS M (07/08/2013) //// UNIX v1 -> u5.s
  2107                              <1> ;
  2108                              <1> ; ****************************************************************************
  2109                              <1> 
  2110                              <1> 	; 09/03/2022
  2111                              <1> 	; 09/01/2022
  2112                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2113                              <1> mget_w:
  2114                              <1> 	; 28/10/2021
  2115                              <1> 	; 22/08/2021
  2116                              <1> 	; 20/08/2021
  2117                              <1> 	; 25/05/2020
  2118                              <1> 	; 24/05/2020 - Retro UNIX 386 v2	
  2119 00005197 C605[42760000]01    <1> 	mov	byte [mget_rw], 1 ; write access
  2120 0000519E EB07                <1> 	jmp	short mget
  2121                              <1> mget_r:
  2122                              <1> 	; 28/10/2021
  2123                              <1> 	; 22/08/2021
  2124                              <1> 	; 25/05/2020
  2125                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2126 000051A0 C605[42760000]00    <1> 	mov	byte [mget_rw], 0 ; read access	
  2127                              <1> mget:
  2128                              <1> 	; 09/03/2022
  2129                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2130                              <1> 	; 28/11/2021
  2131                              <1> 	; 22/11/2021
  2132                              <1> 	; 28/10/2021 - temporary (simplified code)
  2133                              <1> 	; 22/08/2021
  2134                              <1> 	; 20/08/2021
  2135                              <1> 	; 25/05/2020
  2136                              <1> 	; 24/05/2020
  2137                              <1> 	; 05/05/2020
  2138                              <1> 	; 02/05/2020, 03/05/2020
  2139                              <1> 	; 29/04/2020 - Retro UNIX 386 v2
  2140                              <1> 	; New inode model/format (Modified UNIX v7 inode model)
  2141                              <1> 	;	
  2142                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2143                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2144                              <1> 	;
  2145                              <1> 	; Get existing or (allocate) a new disk block for file
  2146                              <1> 	; 
  2147                              <1> 	; INPUTS ->
  2148                              <1> 	;    u.fofp (file offset pointer)
  2149                              <1> 	;    inode 
  2150                              <1> 	;    u.off (file offset)
  2151                              <1> 	; OUTPUTS ->
  2152                              <1> 	;    r1 (physical block number)
  2153                              <1> 	;    r2, r3, r5 (internal)
  2154                              <1> 	;
  2155                              <1> 	; ((AX = R1)) output
  2156                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2157                              <1> 	;
  2158                              <1> 	; Modified registers: eax, edx, ebx, ecx, esi, edi, ebp
  2159                              <1> 
  2160                              <1> 	; Retro UNIX 386 v2 'mget' procedure
  2161                              <1> 	; source code reference:
  2162                              <1> 	; 'mget' procedure in UNIXHDCP.ASM (25/01/2020) by Erdogan Tan
  2163                              <1> 
  2164                              <1> 	; Get sector/block address for current file pointer
  2165                              <1> 	; (If file pointer points to a number greater than current file
  2166                              <1> 	; size, a new -empty- sector/block will be created/written.)
  2167                              <1> 
  2168                              <1> 	; Note: 'mget' procedure will be used for only RUNIX v2 FS.
  2169                              <1> 	;	(installable file system drivers will not use 'mget')
  2170                              <1> 	;	 !!! 512 bytes per sector !!!  ; 02/05/2020
  2171                              <1> 
  2172                              <1> 	; ! 64 bit fofp ! but Retro UNIX 386 v2 kernel will use 32 bit
  2173                              <1> 	; file offset for regular files and directories.
  2174                              <1> 	; ('mget' procedure will be called for regular files & directories)
  2175                              <1> 
  2176                              <1> 	; 28/10/2021
  2177                              <1> 	; Note: 'mget' uses only current inode ([ii], 'inode:')
  2178                              <1> 	; (inode must be loaded at 'inode:' addr by 'iget' before 'mget')  
  2179                              <1> 
  2180                              <1> 		; mov *u.fofp,mq / file offset in mq
  2181                              <1> 		; clr ac / later to be high sig
  2182                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2183                              <1> 		; mov mq,r2
  2184                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2185                              <1> 		; bne 4f / branch for large file
  2186                              <1> 
  2187                              <1> 	; 09/01/2022
  2188                              <1> 	; Return: eax = physical block/sector number
  2189                              <1> mget_0:	
  2190 000051A7 8B35[C0750000]      <1>         mov     esi, [u.fofp]
  2191 000051AD 8B1E                <1> 	mov	ebx, [esi]
  2192                              <1>         ; ebx = file offset
  2193                              <1> 
  2194                              <1> 	; 20/08/2021
  2195 000051AF C1EB09              <1> 	shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2196                              <1> 
  2197 000051B2 F605[59710000]10    <1> 	test	byte [i.flgs+1], 10h ; is this a large or small file addr?
  2198 000051B9 7405                <1> 	jz	short mget_1 ; small file addressing
  2199 000051BB E984000000          <1> 	jmp	mget_5	; large file addressing
  2200                              <1> mget_1:
  2201                              <1> 	; If large file flag is clear -not set- RUNIX v2 FS inode
  2202                              <1> 	; will contain 10 direct disk block/sector dword pointers.
  2203                              <1> 
  2204                              <1> 	; 05/05/2020
  2205                              <1> 	;shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2206                              <1> 
  2207 000051C0 83FB0A              <1> 	cmp	ebx, 10	; block 10
  2208 000051C3 7338                <1> 	jnb	short mget_3 ; file offset >= 5120
  2209                              <1> 
  2210                              <1> 	; 05/05/2020
  2211                              <1> 	;cmp	ebx, 5120
  2212                              <1> 	;jnb	short mget_3 ; file offset >= 5120
  2213                              <1> 
  2214                              <1> 	;mov	bl, bh
  2215                              <1> 	;and	bl, 1Eh ; clear all bits but bits 1,2,3,4 ; 0,2,..,18
  2216                              <1> 	;	; max. value = 12h = 10010b = 18 (because ebx <= 5119) 
  2217                              <1> 	;shl	bl, 1	; * 2 ; max. value = 24h = 100100b = 36
  2218                              <1> 	;xor	bh, bh  ; clear bh
  2219                              <1> 		; RUNIX v2 (RUFS 2) file system bytes per sector value
  2220                              <1> 		; is always 512.
  2221                              <1> 		; ebx = 4*(ebx/512)  = 0 to 36
  2222                              <1> 
  2223                              <1> 	; 05/05/2020
  2224 000051C5 C0E302              <1> 	shl	bl, 2 ; * 4
  2225                              <1> 		 ; ebx = 0 to 36
  2226                              <1> 
  2227 000051C8 8B83[64710000]      <1> 	mov	eax, [ebx+i.dskp] ; disk sector addr ptr 0 to 9 for file
  2228                              <1> 	; 22/08/2021
  2229 000051CE 89DE                <1> 	mov	esi, ebx
  2230                              <1> 	;xor	ebx, ebx ; 0
  2231                              <1> 	; 09/03/2022
  2232                              <1> 	;; 09/01/2022
  2233                              <1> 	;xor	bl, bl
  2234                              <1> 
  2235 000051D0 09C0                <1> 	or	eax, eax
  2236 000051D2 7512                <1> 	jnz	short mget_2 ; existing block/sector (logical)
  2237                              <1> 
  2238 000051D4 56                  <1> 	push	esi ; * ; 22/08/2021
  2239 000051D5 E875010000          <1> 	call	alloc_m ; 24/05/2020	
  2240                              <1> 	;call	alloc	; allocate a new sector/block for this file	
  2241                              <1> 			; eax = sector/block number
  2242                              <1> 			; ebx = buffer header address
  2243 000051DA 5E                  <1> 	pop	esi ; * ; 22/08/2021
  2244                              <1> 	; 28/11/2021
  2245                              <1> 	;jc	short mget_2 
  2246                              <1> 			; cf = 1 -> eax = 'no free block' error
  2247                              <1> 	; 22/08/2021
  2248 000051DB 8986[64710000]      <1> 	mov	[esi+i.dskp], eax  ; logical sector/block address
  2249                              <1> 
  2250                              <1> 	; 09/01/2022
  2251 000051E1 E8C0040000          <1> 	call	setimod	; set inode modification flag
  2252                              <1> 			; and set modification time
  2253                              <1> 
  2254                              <1> 	; eax = logical sector/block number
  2255                              <1> 	; ([idev] = logical drive number)
  2256                              <1> 	; 28/10/2021
  2257                              <1> 	; [cdev] = logical drive number (0 or 1)
  2258                              <1> 	;	(0 = root fs, 1 = mounted fs)
  2259                              <1> mget_2:
  2260                              <1> 	; 09/01/2022
  2261                              <1> 	; eax = logical sector/block number
  2262 000051E6 F605[8D750000]01    <1> 	test	byte [cdev], 1
  2263 000051ED 7507                <1> 	jnz	short mget_14
  2264                              <1> 	; convert to physical sector/block number
  2265 000051EF 0305[5C760000]      <1> 	add	eax, [systm+SB.BootSectAddr]
  2266 000051F5 C3                  <1> 	retn
  2267                              <1> 	; 09/01/2022
  2268                              <1> mget_14:
  2269                              <1> 	; convert to physical sector/block number
  2270 000051F6 0305[64780000]      <1> 	add	eax, [mount+SB.BootSectAddr]
  2271 000051FC C3                  <1> 	retn
  2272                              <1> 	
  2273                              <1> 		; rts r0
  2274                              <1> mget_3: ; 3: / adding on block which changes small file to a large file
  2275                              <1> 	; 22/11/2021
  2276 000051FD E84D010000          <1> 	call	alloc_m ; 24/05/2020
  2277                              <1> 	;call	alloc	; allocate a new sector/block for this file
  2278                              <1> 			; eax = sector/block number
  2279                              <1> 			; ebx = buffer header  ; 24/05/2020
  2280                              <1> 	; 28/11/2021
  2281                              <1> 	;jc	short mget_2 ; error code in eax
  2282                              <1> 
  2283                              <1> 	; 09/01/2022
  2284                              <1> 	; convert to physical block/sector number
  2285 00005202 50                  <1> 	push	eax ; *!* ; logical sector/block number 
  2286 00005203 E8DEFFFFFF          <1> 	call	mget_2
  2287                              <1> 
  2288                              <1>         ; EAX (r1) = Physical block (sector) number
  2289 00005208 E875100000          <1> 	call 	wslot
  2290                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2291                              <1> 			     ; / first data word in buffer
  2292                              <1>         ; EAX (r1) = Physical block number
  2293                              <1> 	; 28/11/2021
  2294                              <1> 	; ebx = buffer (data) address
  2295                              <1> 	; 22/11/2021
  2296 0000520D 31C9                <1> 	xor	ecx, ecx
  2297 0000520F B10A                <1> 	mov 	cl, 10	; r3, transfer old physical block pointers
  2298                              <1> 			; into new indirect block area for the new
  2299                              <1> 			; large file		
  2300 00005211 89DF                <1> 	mov 	edi, ebx ; r5
  2301 00005213 BE[64710000]        <1> 	mov	esi, i.dskp  ; current inode's direct disk addr ptrs
  2302 00005218 89C2                <1> 	mov	edx, eax
  2303 0000521A 31C0                <1> 	xor	eax, eax
  2304                              <1> mget_4:
  2305 0000521C A5                  <1> 	movsd 	
  2306 0000521D 8946FC              <1> 	mov	[esi-4], eax ; 0
  2307 00005220 E2FA                <1> 	loop	mget_4
  2308                              <1> 
  2309                              <1> 	; 22/11/2021
  2310 00005222 B176                <1> 	mov 	cl, 128-10 ; clear rest of data buffer
  2311                              <1> ;mget_4: ; 1
  2312 00005224 F3AB                <1> 	rep 	stosd
  2313                              <1> 		; clr (r5)+
  2314                              <1> 		; dec r3
  2315                              <1> 		; bgt 1b
  2316 00005226 89D0                <1> 	mov	eax, edx
  2317                              <1>         ; EAX (r1) = Physical block number
  2318 00005228 E871100000          <1> 	call	dskwr
  2319                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2320                              <1> 
  2321                              <1> 	;; EAX (r1) = Physical block number
  2322                              <1> 
  2323                              <1> 	; 09/01/2022        
  2324 0000522D 8F05[64710000]      <1> 	pop	dword [i.dskp] ; *!* ; logical sector/block number
  2325                              <1>  
  2326                              <1> 	; eax = logical disk sector/block number/addr ; 09/01/2022
  2327                              <1> 	;mov 	[i.dskp], eax ; 22/11/2021 
  2328                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2329                              <1> 
  2330 00005233 800D[59710000]10    <1> 	or	byte [i.flgs+1], 10000b ; 10h ; 16  ; large file flag
  2331                              <1> 		; bis $10000,i.flgs / set large file bit 
  2332                              <1> 				  ; / in i.flgs word of i-node
  2333 0000523A E867040000          <1> 	call	setimod
  2334                              <1> 		; jsr r0,setimod / set i-node modified flag
  2335                              <1> 
  2336 0000523F E963FFFFFF          <1> 	jmp	mget_0 ; 09/01/2022
  2337                              <1> 		; br mget
  2338                              <1> 
  2339                              <1> mget_5:  ; 4 ; large file
  2340                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2341                              <1> 	;
  2342                              <1> 	; Retro UNIX 386 v2 disk inode contains..
  2343                              <1> 	; (if large file flag is set)
  2344                              <1> 	; 8 indirect disk block/sector dword pointers
  2345                              <1> 	; +1 double indirect disk block/sector dword pointers
  2346                              <1> 	; +1 triple indirect disk block/sector dword pointers
  2347                              <1> 
  2348                              <1> 	; check indirect pointers limit (as file offset)
  2349                              <1> 	; 8*128 = 1024 blocks (or sectors) or 512 KB
  2350                              <1> 	; check dx (file offset hw) value
  2351                              <1> 	
  2352                              <1> 	; 03/05/2020
  2353                              <1> 	;cmp	ebx, 524288  ; is file offset >= 524288 ?
  2354                              <1> 	;jnb	short mget_6 ; yes, check double indirect limit
  2355                              <1> 
  2356                              <1> 	; 05/05/2020
  2357 00005244 81FB00040000        <1> 	cmp	ebx, 1024    ; block 1024 (byte 524288)	
  2358 0000524A 7321                <1> 	jnb	short mget_6 ; check double indirect limit
  2359                              <1> 
  2360 0000524C C605[44760000]01    <1> 	mov	byte [level], 1 ; levels, 1 = indirect blocks
  2361                              <1> 
  2362                              <1> 	; 05/05/2020
  2363                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2364                              <1> 
  2365 00005253 88D9                <1> 	mov	cl, bl
  2366 00005255 80E17F              <1> 	and	cl, 127
  2367 00005258 880D[45760000]      <1> 	mov	[level+1], cl ; level 1, direct block ptr index (0 to 127)
  2368 0000525E 66C1EB07            <1> 	shr	bx, 7 ; bl = level 0, indirect block pointer index (0 to 7)
  2369                              <1> 	;mov	[level+2], bl
  2370                              <1> 
  2371 00005262 C0E302              <1> 	shl	bl, 2 ; * 4 to convert index number to offset
  2372                              <1> 
  2373                              <1> 	;mov	esi, i.dskp
  2374                              <1> 	;add	esi, ebx
  2375                              <1> 
  2376 00005265 8DB3[64710000]      <1> 	lea	esi, [ebx+i.dskp]
  2377                              <1> 
  2378 0000526B EB66                <1> 	jmp	short mget_8
  2379                              <1> 
  2380                              <1> mget_6:
  2381                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2382                              <1> 	; 03/05/2020
  2383                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2384                              <1> 	; check double indirect pointer limit (as file offset)
  2385                              <1> 	; (128*128)+1024 = 16384+1024 blocks or 8 MB + 512 KB
  2386                              <1> 	; check dx (file offset hw) value
  2387                              <1> 	
  2388                              <1> 	;cmp	ebx, 8912896 ; >= 17408 sectors (16384+1024) ?	
  2389                              <1> 	;jnb	short mget_7 ; yes, use triple indirect pointer (block)
  2390                              <1> 
  2391                              <1> 	; 05/05/2020
  2392 0000526D 81FB00440000        <1> 	cmp	ebx, 17408   ; block 17408 (byte 8912896)	
  2393 00005273 7329                <1> 	jnb	short mget_7 ; use triple indirect pointer (block)
  2394                              <1> 
  2395 00005275 C605[44760000]02    <1> 	mov	byte [level], 2  ; levels, 2 = double indirect blocks
  2396                              <1> 	
  2397                              <1> 	;sub	ebx, 524288 ; 1024 sectors
  2398                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2399                              <1> 			; (from sector 1024)
  2400                              <1> 	; 05/05/2020
  2401 0000527C 81EB00040000        <1> 	sub	ebx, 1024 ; offset from sector 1024
  2402                              <1> 	
  2403 00005282 88D9                <1> 	mov	cl, bl
  2404 00005284 80E17F              <1> 	and	cl, 127
  2405 00005287 880D[45760000]      <1> 	mov	[level+1], cl
  2406                              <1> 			; level 2, direct block ptr index (0 to 127)	
  2407 0000528D 66C1EB07            <1> 	shr	bx, 7
  2408 00005291 881D[46760000]      <1> 	mov	[level+2], bl
  2409                              <1> 			; level 1, indirect block ptr index (0 to 127)
  2410                              <1> 
  2411 00005297 BE[84710000]        <1> 	mov	esi, i.dskp + 32 ; 8*4
  2412                              <1> 			; level 0, double indirect block pointer
  2413 0000529C EB35                <1> 	jmp	short mget_8
  2414                              <1> 
  2415                              <1> mget_7:
  2416                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2417                              <1> 	; 03/05/2020
  2418                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2419                              <1> 	; triple indirect pointer ; 8912896 to 1082654720 bytes
  2420                              <1> 	;mov	esi, i.dskp + 36 ; 9*4
  2421                              <1> 
  2422 0000529E C605[44760000]03    <1> 	mov	byte [level], 3  ; levels, 3 = triple indirect blocks
  2423                              <1> 
  2424                              <1> 	;sub	ebx, 8912896 ; 17408 sectors (16384+1024)
  2425                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2426                              <1> 			; (from sector 17408)
  2427                              <1> 	; 05/05/2020
  2428 000052A5 81EB00440000        <1> 	sub	ebx, 17408 ; offset from sector 17408	
  2429                              <1> 
  2430 000052AB 88D9                <1> 	mov	cl, bl
  2431 000052AD 80E17F              <1> 	and	cl, 127
  2432 000052B0 880D[45760000]      <1> 	mov	[level+1], cl  
  2433                              <1> 			; level 3, direct block ptr index (0 to 127)	
  2434 000052B6 C1EB07              <1> 	shr	ebx, 7	
  2435 000052B9 88D9                <1> 	mov	cl, bl
  2436 000052BB 80E17F              <1> 	and	cl, 127
  2437 000052BE 880D[46760000]      <1> 	mov	[level+2], cl
  2438                              <1> 			; level 2, indirect block ptr index (0 to 127)
  2439 000052C4 66C1EB07            <1> 	shr	bx, 7
  2440 000052C8 881D[47760000]      <1> 	mov	[level+3], bl
  2441                              <1> 			; level 1, double indir blk ptr index (0 to 127)
  2442                              <1> 
  2443 000052CE BE[88710000]        <1> 	mov	esi, i.dskp + 36 ; 9*4
  2444                              <1> 			; level 0, triple indirect block pointer
  2445                              <1> mget_8:
  2446                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2447 000052D3 8B06                <1> 	mov	eax, [esi]
  2448 000052D5 09C0                <1> 	or 	eax, eax ; R1
  2449 000052D7 751A                <1> 	jnz 	short mget_10 ; 2f
  2450                              <1> 		; bne 2f / if no indirect block exists
  2451 000052D9 56                  <1> 	push	esi	; * ; 24/05/2020
  2452                              <1> 
  2453 000052DA E870000000          <1> 	call	alloc_m ; 24/05/2020
  2454                              <1> 	;call	alloc	; allocate a new block for this file	
  2455                              <1> 			; eax = block number
  2456                              <1> 			; ebx = buffer header address
  2457                              <1> 			; [pdn] = physical drive number ; 25/05/2020
  2458                              <1> 	;jc	mget_2	; cf -> 1 & eax = 0 -> no free block
  2459                              <1> 
  2460 000052DF 5E                  <1> 	pop	esi	; * ; 24/05/2020
  2461                              <1> 	;jc	short mget_9
  2462                              <1> 
  2463                              <1> 	; 09/01/2022
  2464                              <1> 	; eax = logical sector/block number
  2465                              <1> 
  2466 000052E0 8906                <1> 	mov	[esi], eax ; record sector/block address on i.dskp area
  2467                              <1> 
  2468 000052E2 E8BF030000          <1> 	call 	setimod
  2469                              <1> 		; jsr r0,setimod / set i-node modified byte
  2470                              <1> 	; EAX = new block number (logical)
  2471                              <1> 
  2472                              <1> 	; 09/01/2022
  2473                              <1> 	; convert to physical block/sector number
  2474 000052E7 E8FAFEFFFF          <1> 	call	mget_2
  2475                              <1> 	;
  2476 000052EC E8ABFDFFFF          <1> 	call 	clear
  2477                              <1> 		; jsr r0,clear / clear new block
  2478                              <1> 	; 09/03/2022
  2479                              <1> 	;add	ebx, 8
  2480                              <1> 	; ebx = buffer data address
  2481                              <1> 	; 22/11/2021
  2482 000052F1 EB0A                <1> 	jmp	short mget_11
  2483                              <1> ;mget_9:
  2484                              <1> ;	pop	edx ; *  ; 09/01/2022
  2485                              <1> ;	retn
  2486                              <1> mget_10: ;2
  2487                              <1> 	; 09/01/2022
  2488                              <1> 	; eax = logical sector/block number/address
  2489                              <1> 	; convert to physical sector/block number/address
  2490 000052F3 E8EEFEFFFF          <1> 	call	mget_2	
  2491                              <1> 	; 05/03/2013
  2492                              <1> 	; EAX = r1, physical block number (of indirect block)
  2493 000052F8 E8130F0000          <1> 	call 	dskrd ; read indirect block
  2494                              <1> 		; jsr r0,dskrd / read in indirect block
  2495                              <1> 	;jc	short mget_9
  2496                              <1> mget_11:
  2497                              <1> 	; 22/11/2021
  2498                              <1> 	; eax = physical block/sector address
  2499                              <1> 	; ebx = buffer (data) address ; 09/03/2022
  2500                              <1> 
  2501 000052FD 89C2                <1> 	mov	edx, eax ; *  ; save physical sector number in edx
  2502                              <1> 
  2503 000052FF 0FB605[44760000]    <1> 	movzx	eax, byte [level]
  2504 00005306 8A80[44760000]      <1> 	mov	al, [eax+level] ; get sector pointer offset
  2505 0000530C C1E002              <1> 	shl	eax, 2 ; * 4 ; 09/01/2022
  2506                              <1> 	;shl	ax, 2 ; * 4
  2507                              <1> 
  2508 0000530F 01C3                <1> 	add	ebx, eax
  2509                              <1> 
  2510 00005311 8B03                <1> 	mov 	eax, [ebx] ; put logical block no of block
  2511                              <1> 			   ; in file sought in R1 (EAX)
  2512                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2513                              <1> 	               	    ; / sought in r1
  2514                              <1> 
  2515 00005313 21C0                <1> 	and	eax, eax  ; if logical sector/block number is zero
  2516                              <1> 			  ; then we need a new block for file
  2517 00005315 740D                <1> 	jz	short mget_12
  2518                              <1> 
  2519 00005317 FE0D[44760000]      <1> 	dec	byte [level]
  2520 0000531D 75D4                <1> 	jnz	short mget_10
  2521                              <1> 
  2522                              <1> 	; 09/03/2022
  2523                              <1> 	;sub	ebx, ebx ; ebx = 0 ; existing sector
  2524                              <1> 
  2525                              <1> 	;retn
  2526                              <1> 	; 09/01/2022
  2527                              <1> 	; eax = logical block/sector number
  2528 0000531F E9C2FEFFFF          <1> 	jmp	mget_2
  2529                              <1> 
  2530                              <1> mget_12:
  2531                              <1> 	; 22/11/2021
  2532 00005324 52                  <1> 	push	edx ; *
  2533 00005325 53                  <1> 	push	ebx ; ** ; buffer data position
  2534 00005326 E824000000          <1> 	call	alloc_m
  2535                              <1> 	;call	alloc	 ; allocate a new block for this file	
  2536                              <1> 			 ; eax = block number (logical)
  2537                              <1> 			 ; ebx = buffer header address
  2538 0000532B 5E                  <1> 	pop	esi ; **
  2539                              <1> 	; 09/01/2022
  2540                              <1> 	;pop	edx ; *
  2541                              <1> 	;jc	short mget_9 ; cf -> 1 & eax = 0 -> no free block
  2542                              <1> 
  2543 0000532C 8906                <1> 	mov	[esi], eax ; record/save block number (logical)
  2544                              <1> 
  2545                              <1> 	; 22/11/2021
  2546 0000532E 870424              <1> 	xchg	eax, [esp] ; *
  2547                              <1> 
  2548                              <1> 	; eax (r1) = physical block number (of indirect block)
  2549 00005331 E84C0F0000          <1> 	call 	wslot
  2550                              <1> 		; jsr r0,wslot
  2551                              <1>         ; eax (r1) = physical block number
  2552                              <1> 	; ebx (r5) = pointer to buffer (indirect block)
  2553 00005336 E8630F0000          <1> 	call 	dskwr
  2554                              <1> 	; eax = r1 = physical block number (of indirect block)
  2555                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2556                              <1> 			     ; / back out on disk
  2557 0000533B 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2558                              <1> 		; mov (sp),r1 / restore block number of new block	
  2559                              <1> 
  2560                              <1> 	; 09/01/2022
  2561                              <1> 	; eax = logical sector/block number/address of new block
  2562                              <1> 	; convert to physical sector/block number/address
  2563 0000533C E8A5FEFFFF          <1> 	call	mget_2	
  2564                              <1> 
  2565 00005341 E856FDFFFF          <1> 	call 	clear
  2566                              <1> 		; jsr r0,clear / clear new block
  2567                              <1> 
  2568 00005346 FE0D[44760000]      <1> 	dec	byte [level]
  2569 0000534C 75AF                <1> 	jnz	short mget_11 
  2570                              <1> 		; ebx = buffer (data) address ; 09/03/2022
  2571                              <1> 
  2572                              <1> 	; 09/01/2022
  2573                              <1> 	; eax = physical sector/block number/address of new block
  2574                              <1> 	
  2575                              <1> 	; 22/11/2021
  2576                              <1> 	; ebx = buffer address
  2577                              <1> mget_13: ; 2
  2578                              <1> 	; eax (r1) = Block number of new block
  2579 0000534E C3                  <1> 	retn
  2580                              <1> 		; rts r0
  2581                              <1> 
  2582                              <1> 	; 09/01/2022
  2583                              <1> 	; 26/11/2021
  2584                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2585                              <1> alloc_m:
  2586                              <1> 	; 27/11/2021
  2587                              <1> 	; 28/10/2021
  2588                              <1> 	; 07/05/2021
  2589                              <1> 	; 26/05/2020
  2590                              <1> 	; 25/05/2020
  2591                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2592                              <1> 	; 'alloc' call in 'mget'
  2593                              <1> 	;
  2594                              <1> 	; (('mget_r' will be returned with error))
  2595                              <1> 	; (('mget_w' will continue to 'alloc'))
  2596                              <1> 
  2597                              <1> 	; Note: 'sysread' will return with cf = 0, eax = 0
  2598                              <1> 	; if [fofp] >= file size (eax = 0 --> EOF)
  2599                              <1> 	; So, if we are here, that means [fofp] < file size
  2600                              <1> 	;     but disk address is 0. 
  2601                              <1> 	
  2602 0000534F 803D[42760000]01    <1> 	cmp	byte [mget_rw], 1 ; write access ? (mget_w) 
  2603 00005356 730F                <1> 	jnb	short alloc ; yes (this is a call from 'mget_w')
  2604                              <1> 	; ((cf = 1))	
  2605                              <1> 	; no (this is a call from 'mget_r') !
  2606                              <1> 	;mov	eax, ERR_FILE_SIZE ; file size error (inode error!)
  2607                              <1> 		; [User may change this empty/invalid inode (disk) sector
  2608                              <1> 		; pointer with a new valid inode (disk) sector pointer 
  2609                              <1> 		; by writing new clear (zero) sector to same file position
  2610                              <1> 		; in order to correct file size -inode parm/content- error.
  2611                              <1> 		; It may be useful for recovering lost data if other sector
  2612                              <1> 		; pointers are not empty.]	
  2613                              <1> 	;retn
  2614                              <1> 	; 27/11/2021
  2615 00005358 C705[20760000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE 
  2615 00005360 0000                <1>
  2616                              <1> 			; file size error (inode error!)
  2617 00005362 E9E1E7FFFF          <1> 	jmp	error
  2618                              <1> alloc:
  2619                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2620                              <1> 	; 27/11/2021
  2621                              <1> 	; 26/11/2021 - Major modification for Runix v2 file system
  2622                              <1> 	;	(I have called this kernel version as v1.2, it is a
  2623                              <1> 	;	 debug/test version just before Retro UNIX 386 v2 kernel)
  2624                              <1> 	;	((there were running problems on new version, 
  2625                              <1> 	;	  so i am developing an intermediate version with minimum
  2626                              <1> 	;	  modification on v1.1 code which is successfuly running))
  2627                              <1> 	;	 ; /// Erdogan Tan - Istanbul, 26/11/2021 /// 
  2628                              <1> 	;	 
  2629                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2630                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2631                              <1> 	;
  2632                              <1> 	; get a free block and 
  2633                              <1> 	; set the corresponding bit in the free storage map
  2634                              <1> 	; 
  2635                              <1> 	; INPUTS ->
  2636                              <1> 	;    cdev (current device)
  2637                              <1> 	;    r2 
  2638                              <1> 	;    r3
  2639                              <1> 	; OUTPUTS ->
  2640                              <1> 	;    r1 (physical block number of block assigned)
  2641                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2642                              <1> 	;
  2643                              <1> 	; ((AX = R1)) output
  2644                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2645                              <1>         ;    ((Modified registers: edx, ecx)) 
  2646                              <1> 
  2647                              <1> 	; 26/11/2021
  2648                              <1> 	; INPUT:
  2649                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2650                              <1> 	; OUTPUT:
  2651                              <1> 	;	eax = disk block/sector number/address (physical)
  2652                              <1> 	;	(ebx = disk buffer address for sector/block in eax)
  2653                              <1> 	;
  2654                              <1> 	;    Note:	
  2655                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2656                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2657                              <1> 	;	modification flag will be set; but the superblock 
  2658                              <1> 	;	will not be written to it's disk in this 'alloc' procedure)
  2659                              <1> 	;
  2660                              <1> 	; Modified registers: eax, ebx, ecx, edx, esi, edi, ebp
  2661                              <1> 
  2662                              <1> 	; 09/01/2022
  2663                              <1> 	; Return: eax = logical block/sector number 
  2664                              <1> 
  2665                              <1> 	; 26/11/2021
  2666 00005367 BB[58760000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2667                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2668 0000536C F605[8D750000]01    <1> 	test	byte [cdev], 1
  2669                              <1> 		; tst cdev
  2670 00005373 7405                <1> 	jz	short alloc_1
  2671                              <1> 		; beq 1f / drum is device
  2672 00005375 BB[60780000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2673                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2674                              <1> 			      ; / free storage map
  2675                              <1> alloc_1: ; 1
  2676                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2677 0000537A F6436A01            <1> 	test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2678 0000537E 7507                <1> 	jnz	short alloc_2  ; 'read only file system' error
  2679                              <1> 	;
  2680 00005380 8B4B38              <1> 	mov	ecx, [ebx+SB.FreeBlocks] ; count of free blocks/sectors
  2681 00005383 21C9                <1> 	and	ecx, ecx
  2682 00005385 750F                <1> 	jnz	short alloc_3
  2683                              <1> alloc_2:
  2684                              <1> 	; 'no free blocks on disk !' error
  2685 00005387 C705[20760000]2100- <1> 	mov	dword [u.error], ERR_ALLOC
  2685 0000538F 0000                <1>
  2686 00005391 E9B2E7FFFF          <1> 	jmp	error
  2687                              <1> alloc_3:
  2688                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2689 00005396 31C0                <1> 	xor	eax, eax
  2690                              <1> 	; 23/07/2021
  2691 00005398 8B4B3C              <1> 	mov	ecx, [ebx+SB.FirstFreeBlk] ; 1st free sector number
  2692                              <1> 					 ; (as logical sector number)
  2693 0000539B 09C9                <1> 	or	ecx, ecx
  2694 0000539D 7415                <1> 	jz	short alloc_5 ; 0 = initial/reset value or 'not valid'
  2695 0000539F 41                  <1> 	inc	ecx ; 0FFFFFFFFh -> 0
  2696 000053A0 7412                <1> 	jz	short alloc_5 ; 'not valid' or 'not calculated'
  2697 000053A2 49                  <1> 	dec	ecx ; restore first free block value
  2698 000053A3 89C8                <1> 	mov	eax, ecx
  2699                              <1> 	; 1 allocation byte (in fbm) is for 8 sectors
  2700 000053A5 C1E903              <1> 	shr	ecx, 3	; first free block number / 8
  2701 000053A8 80E1FC              <1> 	and	cl, ~3	; dword alignment (to backward)
  2702                              <1> 	; 27/11/2021
  2703 000053AB 890D[44760000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm
  2704                              <1> alloc_4:
  2705 000053B1 C1E80C              <1> 	shr	eax, 12 ; 1 fbm sector for 4096 sectors
  2706                              <1> alloc_5:
  2707                              <1> 	; 26/11/2021
  2708 000053B4 53                  <1> 	push	ebx ; ** ; superblock buffer address 
  2709                              <1> 	; eax = fbm sector index
  2710 000053B5 A3[48760000]        <1> 	mov	[free_map_index], eax
  2711 000053BA 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2712                              <1> 			; free blocks map start sector addr
  2713                              <1> 	; 09/01/2022
  2714 000053BD 034304              <1> 	add	eax, [ebx+SB.BootSectAddr] 
  2715                              <1> 			; + Hidden Sectors
  2716                              <1> 	;
  2717                              <1> 	; eax = physical sector number
  2718 000053C0 E84B0E0000          <1> 	call	dskrd
  2719                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2720                              <1> 	; eax = physical sector number
  2721                              <1> 	; ebx = buffer data address
  2722                              <1> 	; 27/11/2021
  2723 000053C5 8B15[44760000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2724 000053CB A3[4C760000]        <1> 	mov	[free_map_sector], eax ; physical sector number
  2725 000053D0 B9FF010000          <1> 	mov	ecx, 511
  2726                              <1> 	;and	edx, 511
  2727 000053D5 21CA                <1> 	and 	edx, ecx ; fbm byte offset in fbm buffer
  2728 000053D7 41                  <1> 	inc	ecx ; 512
  2729 000053D8 01D9                <1> 	add	ecx, ebx
  2730 000053DA 01DA                <1> 	add	edx, ebx ; + buffer address
  2731 000053DC 5B                  <1> 	pop	ebx ; ** ; superblock buffer address 
  2732                              <1> 	;
  2733                              <1> 	; ebx = superblock buffer address
  2734                              <1> 	; edx = fbm buffer address + byte offset (dword aligned)
  2735                              <1> 	; ecx = fbm buffer address + 512
  2736                              <1> alloc_6:
  2737                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2738                              <1> 	;		for Retro UNIX 386 v1.2
  2739                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 code
  2740                              <1> 	; (dword scan) ((1 dword = 32 sectors, 1 byte = 8 sectors))
  2741                              <1> 	; ((Note: Logical drive size must be multiplies of 32 sectors))
  2742                              <1> 	; 19/05/2020
  2743                              <1> 	; edx = free blocks map byte address 
  2744 000053DD 0FBC02              <1> 	bsf	eax, [edx] ; Scans source operand for first bit set (1).
  2745                              <1> 			  ; Clear ZF if a bit is found set (1) and 
  2746                              <1> 			  ; loads the destination with an index to
  2747                              <1> 			  ; first set bit. (0 -> 31) 
  2748                              <1> 			  ; Sets ZF to 1 if no bits are found set.
  2749 000053E0 752A                <1> 	jnz	short alloc_8 ; ZF = 0 -> a free block has been found
  2750                              <1> 
  2751 000053E2 A1[44760000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2752 000053E7 83C004              <1> 	add	eax, 4 ; next dword
  2753 000053EA 3B431C              <1> 	cmp	eax, [ebx+SB.FreeMapSize] ; fbm size in bytes
  2754 000053ED 7209                <1> 	jb	short alloc_7
  2755                              <1> 	; invalidate superblock's first free block field
  2756 000053EF C7433CFFFFFFFF      <1> 	mov	dword [ebx+SB.FirstFreeBlk], 0FFFFFFFFh
  2757                              <1> 	; 'no free blocks on disk !' error
  2758 000053F6 EB8F                <1> 	jmp	alloc_2
  2759                              <1> alloc_7:
  2760                              <1> 		; 26/05/2020
  2761                              <1> 		; NOTE: If ldrv size is not multiplies of 32 sectors,
  2762                              <1> 		; mod (ldrv size / 32) sectors (at the end of ldrv)
  2763                              <1> 		; can not be allocated (for regular files or dirs)! 
  2764                              <1> 		; (Kernel or runix fs installation program can use
  2765                              <1> 		;  this fact to save/duplicate critical sectors/data 
  2766                              <1> 		;  onto end sectors of that logical drive's runix fs.)
  2767                              <1> 
  2768                              <1> 	; 26/11/2021
  2769 000053F8 A3[44760000]        <1> 	mov	[free_map_offset], eax
  2770                              <1> 	; 28/07/2021
  2771                              <1> 	; set next first free block value for search
  2772 000053FD C1E003              <1> 	shl	eax, 3 ; * 8 ; first free block
  2773                              <1>  	; 26/11/2021
  2774 00005400 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2775                              <1> 	; search (scan) for next free block map dword (in buffer)
  2776 00005403 83C204              <1> 	add	edx, 4 ; next dword
  2777 00005406 39CA                <1> 	cmp	edx, ecx
  2778 00005408 72D3                <1> 	jb	short alloc_6
  2779                              <1> 	; 27/11/2021
  2780 0000540A EBA5                <1> 	jmp	short alloc_4
  2781                              <1> 
  2782                              <1> alloc_8:
  2783                              <1> 	; 26/11/2021
  2784                              <1> 	; convert bit index to xor value
  2785                              <1> 	; and then set allocated flag for corresponding fbm bit 
  2786 0000540C 89C1                <1> 	mov	ecx, eax
  2787                              <1> 	;mov	cl, al 
  2788                              <1> 	;sub	eax, eax
  2789                              <1> 	;inc	al ; eax = 1
  2790 0000540E B001                <1> 	mov	al, 1
  2791 00005410 D3E0                <1> 	shl	eax, cl
  2792 00005412 3102                <1> 	xor	[edx], eax  ; clear allocated block's bit in the fbm
  2793                              <1> 	; zero bit means allocated disk block (1 means free disk block) 
  2794                              <1> 
  2795 00005414 A1[44760000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2796                              <1> 		; note: eax is dword aligned (0,4,8,12..) !
  2797 00005419 C1E003              <1> 	shl	eax, 3 ; * 8 ; free block number base
  2798 0000541C 01C8                <1> 	add	eax, ecx ; add allocation bit index (0 to 31)	
  2799 0000541E 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax ; current free block
  2800                              <1> 				; (which is being allocated here)
  2801                              <1> 
  2802                              <1> 	;mov	eax, [ebx+SB.FreeMapAddr] 
  2803                              <1> 	;		; free blocks map start sector addr
  2804                              <1> 	;add	eax, [free_map_index]
  2805                              <1> 	
  2806                              <1> 	;;add	eax, [ebx+SB.BootSectAddr] 
  2807                              <1> 	;		; + Hidden Sectors
  2808                              <1> 	; eax = physical sector number
  2809                              <1> 	
  2810                              <1> 	; 27/11/2021
  2811 00005421 A1[4C760000]        <1> 	mov	eax, [free_map_sector] ; physical sector number
  2812                              <1> 	
  2813 00005426 E8570E0000          <1> 	call	wslot
  2814                              <1> 	; ebx = buffer data address (write operation bit is set)
  2815                              <1> 	; eax = physical sector number
  2816                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2817                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2818                              <1> 
  2819                              <1> 	; 27/11/2021
  2820                              <1> 	;mov	[free_map_buffer], ebx ; save free map buffer address
  2821                              <1> 
  2822 0000542B E86E0E0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2823                              <1> 		      ; (at the beginning/head of the buffer chain)
  2824                              <1> 
  2825                              <1> 	; if we are here, buffer has been written to disk successfully 
  2826                              <1> 	; (otherwise cpu would jump to 'error' address)
  2827                              <1> 
  2828                              <1> 	; set superblock modified flag
  2829 00005430 BA[A0750000]        <1> 	mov	edx, smod
  2830 00005435 BB[58760000]        <1> 	mov	ebx, systm
  2831 0000543A F605[8D750000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2832 00005441 7406                <1> 	jz	short alloc_9  ; no, root device
  2833                              <1> 	; yes, mounted device
  2834 00005443 BB[60780000]        <1> 	mov	ebx, mount
  2835                              <1> 	;mov	edx, mmod
  2836 00005448 42                  <1> 	inc	edx ; edx = offset mmod
  2837                              <1> alloc_9: 
  2838 00005449 FE02                <1> 	inc	byte [edx] ; superblock modified !
  2839                              <1> 	
  2840                              <1> 	; Allocating a new sector/block (for file) has been completed here.
  2841 0000544B 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2842 0000544E 40                  <1> 	inc	eax ; 0FFFFFFFFh -> 0 
  2843 0000544F 7405                <1> 	jz	short alloc_10 ; not valid (not set)
  2844 00005451 48                  <1> 	dec	eax ; Free Blocks
  2845 00005452 48                  <1> 	dec	eax ; Free Blocks = Free Blocks - 1
  2846 00005453 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax
  2847                              <1> alloc_10:
  2848 00005456 E80B0F0000          <1> 	call	get_system_time
  2849                              <1> 		; eax = current time (as unix epoch time)
  2850                              <1> 	; 30/07/2021
  2851 0000545B 89435C              <1> 	mov	[ebx+SB.ModifTime], eax
  2852                              <1> 
  2853 0000545E 8B433C              <1> 	mov	eax, [ebx+SB.FirstFreeBlk] ; allocated block address
  2854 00005461 FF433C              <1> 	inc	dword [ebx+SB.FirstFreeBlk] 
  2855                              <1> 				; +1, new value of first free block
  2856                              <1> 				; (new search will be started from here)
  2857                              <1> 				; ((it may not be free, no problem))
  2858                              <1> 
  2859                              <1> 	; put free map buffer address in ebx
  2860                              <1> 	; 27/11/2021
  2861                              <1> 	;mov	ebx, [free_map_buffer]
  2862                              <1> 
  2863 00005464 C3                  <1> 	retn	
  2864                              <1> 
  2865                              <1> 	; 11/02/2022
  2866                              <1> 	; 09/01/2022
  2867                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2868                              <1> free:
  2869                              <1> 	; 09/03/2022
  2870                              <1> 	; 11/02/2022
  2871                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2872                              <1> 	; 05/11/2021
  2873                              <1> 	; 29/10/2021 - temporary (simplified code)
  2874                              <1> 	; 14/08/2021
  2875                              <1> 	; 12/06/2021
  2876                              <1> 	; 07/06/2020
  2877                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  2878                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2879                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2880                              <1> 	;
  2881                              <1> 	; calculates byte address and bit position for given block number
  2882                              <1> 	; then sets the corresponding bit in the free storage map
  2883                              <1> 	; 
  2884                              <1> 	; INPUTS ->
  2885                              <1> 	;    r1 - block number for a block structured device
  2886                              <1> 	;    cdev - current device 
  2887                              <1> 	; OUTPUTS ->
  2888                              <1> 	;    free storage map is updated
  2889                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2890                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2891                              <1> 	;
  2892                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2893                              <1>         ;  ((Modified registers: DX, CX))  
  2894                              <1> 
  2895                              <1> 	; 27/11/2021
  2896                              <1> 	; INPUT:
  2897                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2898                              <1> 	;	eax = disk block/sector number/address (logical)
  2899                              <1> 	; OUTPUT:
  2900                              <1> 	;	ebx = superblock buffer address
  2901                              <1> 	;
  2902                              <1> 	;    Note:	
  2903                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2904                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2905                              <1> 	;	modification flag will be set; but the superblock 
  2906                              <1> 	;	will not be written to it's disk in this 'free' procedure)
  2907                              <1> 	;
  2908                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp 
  2909                              <1> 
  2910                              <1> 	; 27/11/2021
  2911 00005465 BB[58760000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2912 0000546A F605[8D750000]01    <1> 	test	byte [cdev], 1
  2913 00005471 7405                <1> 	jz	short free_1
  2914 00005473 BB[60780000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2915                              <1> free_1: ; 1
  2916                              <1> 	; 11/02/2022
  2917                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2918 00005478 F6436A01            <1> 	test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2919 0000547C 740F                <1> 	jz	short free_2 
  2920                              <1> 	; 'read only file system' error
  2921 0000547E C705[20760000]1E00- <1> 	mov	dword [u.error], ERR_READ_ONLY_FS
  2921 00005486 0000                <1>
  2922 00005488 E9BBE6FFFF          <1> 	jmp	error
  2923                              <1> free_2:
  2924 0000548D 89C1                <1> 	mov	ecx, eax ; logical sector/block number
  2925 0000548F A3[4C760000]        <1> 	mov	[free_map_sector], eax
  2926 00005494 C1E903              <1> 	shr	ecx, 3	; convert to fbmap byte offset
  2927 00005497 C1E80C              <1> 	shr	eax, 12 ; convert to fbmap sector index 
  2928                              <1> 			; (1 fb sector for 4096 sectors)
  2929                              <1> 	;and	cl, ~3	; dword alignment (to backward)
  2930                              <1> 	; 11/02/2022
  2931                              <1> 	;and	ecx, 511 ; convert to offset within fbm buffer
  2932 0000549A 81E1FC010000        <1> 	and	ecx, 1FCh ; 508, dword aligned offset (32 bit scan)
  2933                              <1> 	;
  2934 000054A0 890D[44760000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm buffer
  2935                              <1> 	; 27/11/2021
  2936                              <1> 	; eax = fbm sector index
  2937 000054A6 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2938                              <1> 			; free blocks map start sector address
  2939                              <1> 	; 09/01/2022
  2940 000054A9 034304              <1> 	add	eax, [ebx+SB.BootSectAddr]
  2941                              <1> 			; + Hidden Sectors
  2942                              <1> 	; ebx = superblock address
  2943                              <1> 	; eax = physical sector number
  2944 000054AC E85F0D0000          <1> 	call	dskrd
  2945                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2946                              <1> 	; eax = physical sector number
  2947                              <1> 	; ebx = buffer data address
  2948                              <1> 	; 27/11/2021
  2949 000054B1 A3[48760000]        <1> 	mov	[free_map_index], eax  ; save physical sector address
  2950 000054B6 8B15[44760000]      <1> 	mov	edx, [free_map_offset] ; byte position in fbm buffer
  2951                              <1> 	; 11/02/2022
  2952                              <1> 	;(EDX contains -rounded down- dword aligned offset value)
  2953 000054BC 01DA                <1> 	add	edx, ebx ; + buffer start address
  2954                              <1> 	;
  2955 000054BE 29C0                <1> 	sub	eax, eax
  2956 000054C0 A0[4C760000]        <1> 	mov	al, [free_map_sector] ; logical sector number
  2957                              <1> 	;and	al, 7
  2958                              <1> 	; 11/02/2022
  2959 000054C5 241F                <1> 	and	al, 31 ; 32 bit fbm scan (with dword aligned offset)
  2960                              <1> 
  2961                              <1> 	; al = bit offset in fbm allocation byte
  2962                              <1> 	; edx = buffer address (start+offset)
  2963                              <1> 	; [free_map_offset] = byte position on fbm
  2964                              <1> 	; 27/11/2021
  2965 000054C7 0FAB02              <1> 	bts	[edx], eax  ; copy value of bit position in eax to cf
  2966                              <1> 			    ; then set same bit position at [edx]
  2967 000054CA 7305                <1> 	jnc	short free_3 ; it was allocated sector
  2968                              <1> 
  2969                              <1> 	; already free sector !? 
  2970                              <1> 	; (nonsence or defective fs)
  2971                              <1> 
  2972 000054CC 30C0                <1> 	xor	al, al ; 0  ; eax = 0
  2973 000054CE 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2974                              <1> 	;mov	[ebx+SB.FreeBlocks], eax 
  2975                              <1> 		; invalidate free blocks count
  2976 000054CF EB18                <1> 	jmp	short free_5
  2977                              <1> free_3:
  2978                              <1> 	; 27/11/2021
  2979 000054D1 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2980 000054D4 40                  <1> 	inc	eax
  2981                              <1> 	;jz	short free_4 ; 0FFFFFFFFh -> 0 (invalid!)
  2982                              <1> 	; 09/03/2022
  2983 000054D5 7501                <1> 	jnz	short free_4
  2984 000054D7 48                  <1> 	dec	eax  ; 0 -> 0FFFFFFFFh (invalid!)
  2985                              <1> free_4: 
  2986 000054D8 50                  <1> 	push	eax ; * ; number of free blocks 
  2987                              <1> 	;mov	eax, [free_map_index] ; fbm sector index
  2988                              <1> 	;add	eax, [ebx+SB.FreeMapAddr] 
  2989                              <1> 			; free blocks map start sector address
  2990                              <1> 	;add	eax, [ebx+SB.BootSectAddr]
  2991                              <1> 	;		; + Hidden Sectors
  2992 000054D9 A1[48760000]        <1> 	mov	eax, [free_map_index] ; restore physical sector address
  2993                              <1> 	; eax = physical sector number
  2994 000054DE E89F0D0000          <1> 	call	wslot
  2995                              <1> 	; ebx = buffer data address (write operation bit is set)
  2996                              <1> 	; eax = physical sector number
  2997                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2998                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2999                              <1> 
  3000 000054E3 E8B60D0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  3001                              <1> 		      ; (at the beginning/head of the buffer chain)
  3002                              <1> 
  3003                              <1> 	; if we are here, buffer has been written to disk successfully 
  3004                              <1> 	; (otherwise cpu would jump to 'error' address)
  3005 000054E8 58                  <1> 	pop	eax ; *  ; number of free blocks 
  3006                              <1> free_5:
  3007                              <1> 	; eax = number of free blocks 
  3008                              <1> 	;
  3009                              <1> 	; set superblock modified flag
  3010 000054E9 BA[A0750000]        <1> 	mov	edx, smod
  3011 000054EE BB[58760000]        <1> 	mov	ebx, systm
  3012 000054F3 F605[8D750000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  3013 000054FA 7406                <1> 	jz	short free_6 ; no, root device
  3014                              <1> 	; yes, mounted device
  3015 000054FC BB[60780000]        <1> 	mov	ebx, mount
  3016                              <1> 	;mov	edx, mmod
  3017 00005501 42                  <1> 	inc	edx ; edx = offset mmod
  3018                              <1> free_6: 
  3019 00005502 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax 
  3020                              <1> 
  3021 00005505 A1[4C760000]        <1> 	mov	eax, [free_map_sector] ; logical sector number
  3022 0000550A 3B433C              <1> 	cmp	eax, [ebx+SB.FirstFreeBlk]
  3023 0000550D 7303                <1> 	jnb	short free_7
  3024 0000550F 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  3025                              <1> free_7:
  3026 00005512 FE02                <1> 	inc	byte [edx] ; superblock modified !
  3027 00005514 C3                  <1> 	retn
  3028                              <1> 	
  3029                              <1> iget:
  3030                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3031                              <1> 	; 30/11/2021
  3032                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3033                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3034                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  3035                              <1> 	;
  3036                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  3037                              <1> 	;
  3038                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  3039                              <1> 	; 
  3040                              <1> 	; INPUTS ->
  3041                              <1> 	;    ii - current i-number, rootdir
  3042                              <1> 	;    cdev - new i-node device
  3043                              <1> 	;    idev - current i-node device
  3044                              <1> 	;    imod - current i-node modified flag
  3045                              <1> 	;    mnti - cross device file i-number
  3046                              <1> 	;    r1 - i-numbe rof new i-node
  3047                              <1> 	;    mntd - mountable device number		
  3048                              <1> 	; 	 
  3049                              <1> 	; OUTPUTS ->
  3050                              <1> 	;    cdev, idev, imod, ii, r1
  3051                              <1> 	;
  3052                              <1> 	; ((AX = R1)) input/output
  3053                              <1> 	;
  3054                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3055                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3056                              <1> 
  3057                              <1> 	; 22/11/2021
  3058                              <1> 	;;mov	dl, [cdev] ; 18/07/2013
  3059                              <1> 	;;mov	dh, [idev] ; 07/08/2013
  3060                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3061                              <1> 	;mov	dh, [cdev]
  3062                              <1> 	;mov	dl, [idev]
  3063 00005515 668B15[8C750000]    <1> 	mov	dx, [idev] ; [idev] in dl, [cdev] in dh
  3064                              <1> 	;
  3065                              <1> 	; 22/11/2021
  3066 0000551C 25FFFF0000          <1> 	and	eax, 0FFFFh
  3067 00005521 3B05[88750000]      <1> 	cmp 	eax, [ii]
  3068                              <1> 		; cmp r1,ii / r1 = i-number of current file
  3069 00005527 7504                <1> 	jne 	short iget_1
  3070                              <1> 		; bne 1f
  3071 00005529 38F2                <1> 	cmp	dl, dh
  3072                              <1> 		; cmp idev,cdev
  3073                              <1> 			  ; / is device number of i-node = current device
  3074 0000552B 746C                <1>         je	short iget_5
  3075                              <1> 	;	; beq 2f
  3076                              <1> 	; 14/08/2021
  3077                              <1> iget_1: ; 1:
  3078 0000552D 30DB                <1> 	xor	bl, bl
  3079 0000552F 381D[9E750000]      <1> 	cmp	[imod], bl ; 0	
  3080                              <1> 		; tstb imod / has i-node of current file
  3081                              <1> 			  ; / been modified i.e., imod set
  3082 00005535 7628                <1> 	jna	short iget_2
  3083                              <1> 		; beq 1f
  3084 00005537 881D[9E750000]      <1> 	mov	[imod], bl ; 0
  3085                              <1> 		;  clrb	imod / if it has, 
  3086                              <1> 			   ; / we must write the new i-node out on disk
  3087                              <1> 	; 22/11/2021 (32 bit push-pop)
  3088 0000553D 50                  <1> 	push	eax ; *
  3089                              <1> 		; mov r1,-(sp)
  3090 0000553E 52                  <1> 	push	edx ; **
  3091                              <1> 		; mov cdev,-(sp)
  3092 0000553F A1[88750000]        <1> 	mov	eax, [ii]
  3093                              <1> 		; mov ii,r1
  3094                              <1> 	;mov	dh, [idev]
  3095                              <1> 	;mov	[cdev], dh
  3096                              <1> 	; 09/01/2022
  3097 00005544 8815[8D750000]      <1> 	mov	[cdev], dl  ; dl = [idev]
  3098                              <1> 		; mov idev,cdev
  3099 0000554A FEC3                <1> 	inc	bl ; 1
  3100                              <1> 	; 31/07/2013
  3101 0000554C 881D[40760000]      <1> 	mov     [rw], bl ; 1 == write 
  3102                              <1> 	;;28/07/2013 rw -> u.rw
  3103                              <1>         ;;mov   [u.rw], bl ; 1 == write
  3104 00005552 E843000000          <1> 	call	icalc
  3105                              <1> 		; jsr r0,icalc; 1
  3106 00005557 5A                  <1> 	pop	edx ; **
  3107 00005558 8835[8D750000]      <1> 	mov	[cdev], dh ; 22/11/2021
  3108                              <1> 		; mov (sp)+,cdev
  3109 0000555E 58                  <1> 	pop	eax ; *
  3110                              <1> 		; mov (sp)+,r1
  3111                              <1> iget_2: ; 1:
  3112                              <1> 	;and	ax, ax
  3113 0000555F 21C0                <1> 	and	eax, eax ; 22/11/2021 (32 bit inode number)
  3114                              <1> 		; tst r1 / is new i-number non zero
  3115 00005561 7431                <1> 	jz	short iget_4 ; 2f
  3116                              <1> 		; beq 2f / branch if r1=0
  3117                              <1> 
  3118                              <1> 	;mov 	dh, [cdev]
  3119 00005563 08F6                <1> 	or	dh, dh ; 22/11/2021
  3120                              <1> 		; tst cdev / is the current device number non zero
  3121                              <1> 			 ; / (i.e., device =/ drum)
  3122 00005565 7515                <1> 	jnz	short iget_3 ;  1f
  3123                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  3124                              <1> 	; 22/11/2021
  3125 00005567 3B05[98750000]      <1> 	cmp	eax, [mnti]
  3126                              <1> 	;cmp	ax, [mnti]			
  3127                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  3128                              <1> 			    ; / file (root directory of mounted device)
  3129 0000556D 750D                <1> 	jne	short iget_3 ; 1f
  3130                              <1> 		; bne 1f
  3131                              <1>         ;mov    bl, [mntd]
  3132 0000556F FEC6                <1> 	inc	dh ; mov dh, 1 ; 22/11/2021
  3133 00005571 8835[8D750000]      <1>         mov	[cdev], dh ; 22/11/2021
  3134                              <1> 		; mov mntd,cdev / make mounted device the current device
  3135                              <1> 	; 22/11/2021
  3136 00005577 A1[94750000]        <1> 	mov	eax, [rootdir] ; rootdir = 1 (for runix v2 file system)
  3137                              <1> 	;mov	ax, [rootdir]
  3138                              <1> 		; mov rootdir,r1
  3139                              <1> iget_3: ; 1:
  3140                              <1> 	; 22/11/2021
  3141 0000557C A3[88750000]        <1> 	mov	[ii], eax ; 32 bit inode number
  3142                              <1> 	;mov	[ii], ax
  3143                              <1> 		; mov r1,ii
  3144                              <1> 	; 30/11/2021
  3145 00005581 8835[8C750000]      <1> 	mov	[idev], dh ; cdev 
  3146                              <1> 	;mov	[idev], dl ; cdev
  3147                              <1> 		; mov cdev,idev
  3148 00005587 30DB                <1> 	xor	bl, bl
  3149                              <1>         ; 31/07/2013
  3150 00005589 881D[40760000]      <1> 	mov     [rw], bl ; 0 == read 
  3151                              <1> 	;;28/07/2013 rw -> u.rw       
  3152                              <1>         ;;mov   [u.rw], bl ; 0 = read
  3153 0000558F E806000000          <1> 	call	icalc
  3154                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  3155                              <1> iget_4: ; 2:
  3156                              <1> 	; 22/11/2021
  3157 00005594 A1[88750000]        <1> 	mov	eax, [ii]
  3158                              <1> 	;mov	ax, [ii]
  3159                              <1> 		; mov ii,r1
  3160                              <1> iget_5:
  3161 00005599 C3                  <1> 	retn
  3162                              <1> 		; rts r0
  3163                              <1> 
  3164                              <1> icalc:
  3165                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3166                              <1> 	; 28/11/2021
  3167                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 
  3168                              <1> 	; 02/07/2015
  3169                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3170                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3171                              <1> 	;
  3172                              <1> 	; calculate physical block number from i-number then
  3173                              <1> 	; read or write that block
  3174                              <1> 	;
  3175                              <1> 	; 'icalc' is called from 'iget'
  3176                              <1> 	;
  3177                              <1> 	; for original unix v1:
  3178                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  3179                              <1>        	; / (i+31.) mod 16. bytes from its start
  3180                              <1> 	;
  3181                              <1> 	; for retro unix 8086 v1:
  3182                              <1> 	;  i-node is located in block (i+47)/16 and
  3183                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  3184                              <1> 	;
  3185                              <1> 	; INPUTS ->
  3186                              <1> 	;    r1 - i-number of i-node
  3187                              <1> 	; 	 
  3188                              <1> 	; OUTPUTS ->
  3189                              <1> 	;    inode r/w
  3190                              <1> 	;
  3191                              <1> 	; ((AX = R1)) input
  3192                              <1> 	;
  3193                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3194                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  3195                              <1> 	;
  3196                              <1> 
  3197                              <1> 	; 28/11/2021
  3198                              <1> 	;cmp	byte [idev], 0 ; [cdev] = [idev]
  3199 0000559A 803D[8D750000]00    <1> 	cmp	byte [cdev], 0
  3200 000055A1 7607                <1> 	jna	short icalc_0r
  3201 000055A3 BD[60780000]        <1> 	mov	ebp, mount  ; mounted file system's superblock 
  3202 000055A8 EB05                <1> 	jmp	short icalc_0m
  3203                              <1> icalc_0r:
  3204                              <1> 	; 28/11/2021
  3205 000055AA BD[58760000]        <1> 	mov	ebp, systm  ; root file system's superblock 
  3206                              <1> icalc_0m:
  3207                              <1> 	; 22/11/2021
  3208                              <1> 	;mov	edx, eax
  3209 000055AF 8B15[88750000]      <1> 	mov	edx, [ii] ; 32 bit inode number
  3210 000055B5 8B4528              <1> 	mov	eax, [ebp+SB.InodeTblAddr] ; inode table base address
  3211                              <1> 	;
  3212 000055B8 4A                  <1> 	dec	edx ; 0 based inode number 
  3213                              <1> 		    ; (inode index in inode table)
  3214 000055B9 52                  <1> 	push	edx ; *
  3215 000055BA C1EA03              <1> 	shr	edx, 3
  3216 000055BD 7402                <1> 	jz	short icalc_0t ; 0 for inodes 1 to 8
  3217 000055BF 01D0                <1> 	add	eax, edx
  3218                              <1> icalc_0t:
  3219                              <1> 	; 09/01/2022
  3220                              <1> 	; eax = locical block/sector number 
  3221 000055C1 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  3222                              <1> 	; eax = physical block/sector number 
  3223 000055C4 E8470C0000          <1> 	call	dskrd
  3224                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  3225                              <1> 	; 31/07/2013
  3226 000055C9 803D[40760000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  3227                              <1> 	;; 28/07/2013 rw -> u.rw
  3228                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  3229                              <1> 		; tst (r0)
  3230 000055D0 7605                <1> 	jna	short icalc_1
  3231                              <1> 		; beq 1f / branch to wslot when argument
  3232                              <1> 		       ; / in icalc call = 1
  3233                              <1> 	; eAX = r1 = block number
  3234 000055D2 E8AB0C0000          <1> 	call	wslot
  3235                              <1> 		; jsr r0,wslot / set up data buffer for write
  3236                              <1> 			     ; / (will be same buffer as dskrd got)
  3237                              <1> 	; EBX = r5 points to first word in data area for this block
  3238                              <1> icalc_1: ; 1:
  3239 000055D7 5A                  <1> 	pop	edx ; *
  3240                              <1> 	; 22/11/2021
  3241 000055D8 83E207              <1> 	and 	edx, 07h ; 8 inodes per inode table sector
  3242 000055DB C1E206              <1> 	shl 	edx, 6 ; * 64 (inode size)
  3243                              <1> 	; edx = 64 * (mod(inodenumber-1)/8)
  3244 000055DE 89DE                <1> 	mov	esi, ebx  ; ebx points to 1st word of the buffer
  3245 000055E0 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  3246                              <1>           	; eSI (r5) points to first word in i-node i.	
  3247                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  3248                              <1> 			     ; / 32.*(i+31.)mod16
  3249                              <1> 		; mov $5,lsh / for i-node i.
  3250                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  3251 000055E2 BF[58710000]        <1> 	mov	edi, inode
  3252                              <1> 		; mov $inode,r1 / inode is address of first word 
  3253                              <1> 			      ; / of current i-node
  3254                              <1> 	;mov 	ecx, 8 ; 02/07/2015 (32 bit modification)
  3255                              <1> 	;	; mov $16.,r3
  3256                              <1> 	; 28/11/2021
  3257 000055E7 29C9                <1> 	sub	ecx, ecx
  3258 000055E9 B110                <1> 	mov	cl, 16 ; Retro UNIX 386 v2 inode size = 64 bytes
  3259                              <1> 	; 31/07/2013
  3260 000055EB 382D[40760000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3261                              <1>        ;;28/07/2013 rw -> u.rw                 
  3262                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3263                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  3264 000055F1 7609                <1> 	jna	short icalc_3
  3265                              <1> 		; beq 2f / r0 now contains proper return address 
  3266                              <1> 		       ; / for rts r0
  3267                              <1> icalc_2: ; 1:
  3268 000055F3 87F7                <1> 	xchg 	esi, edi
  3269                              <1> 	; overwrite old i-node (in buffer to be written)
  3270 000055F5 F3A5                <1> 	rep 	movsd
  3271                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  3272                              <1> 		; dec r3
  3273                              <1> 		; bgt 1b
  3274                              <1> 	;call	dskwr
  3275                              <1> 	;	; jsr r0,dskwr / write inode out on device
  3276                              <1> 	;retn
  3277                              <1> 	;	; rts r0
  3278                              <1> 	; 28/11/2021
  3279 000055F7 E9A20C0000          <1> 	jmp	dskwr
  3280                              <1> icalc_3: ; 2:
  3281                              <1> 	; copy new i-node into inode area of (core) memory
  3282 000055FC F3A5                <1> 	rep 	movsd
  3283                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  3284                              <1> 		                ; / "inode" area of core
  3285                              <1> 		; dec r3
  3286                              <1> 		; bgt 2b
  3287 000055FE C3                  <1> 	retn
  3288                              <1> 		; rts r0
  3289                              <1> 
  3290                              <1> access:
  3291                              <1> 	; 13/03/2022
  3292                              <1> 	; 25/12/2021
  3293                              <1> 	; 19/12/2021
  3294                              <1> 	; 28/11/2021
  3295                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3296                              <1> 	; 31/10/2021 - temporary (simplified code)
  3297                              <1> 	; 14/06/2021
  3298                              <1> 	; 02/05/2021
  3299                              <1> 	; 27/03/2021
  3300                              <1> 	; 26/03/2021
  3301                              <1> 	; 25/03/2021
  3302                              <1> 	; 23/03/2021 (Retro UNIX 386 v2 - Beginning)
  3303                              <1> 	;	((ref: unix v7 source - fio.c))
  3304                              <1> 	; ref: INODE STRUCTURE of Retro UNIX v2 file system
  3305                              <1> 	;	07/02/2020, 'RETRO UNIX v2 Inodes.pdf'
  3306                              <1> 	;	 
  3307                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3308                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3309                              <1> 	;
  3310                              <1> 	; check whether user is owner of file or user has read or write
  3311                              <1> 	; permission (based on i.flgs).
  3312                              <1> 	;
  3313                              <1> 	; INPUTS ->
  3314                              <1> 	;    r1 - i-number of file
  3315                              <1> 	;    u.uid
  3316                              <1> 	; arg0 -> (owner flag mask)	 		
  3317                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  3318                              <1> 	; OUTPUTS ->
  3319                              <1> 	;    inode (or jump to error)
  3320                              <1> 	;
  3321                              <1> 	; ((AX = R1)) input/output
  3322                              <1> 	;
  3323                              <1> 	;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))
  3324                              <1> 
  3325                              <1> 	; 26/03/2021
  3326                              <1> 	; INPUT:
  3327                              <1> 	;	eax = inode number (ax)
  3328                              <1> 	;	 dx = mode (IEXEC, IREAD or IWRITE) 
  3329                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3330                              <1> 	;	
  3331                              <1> 	; OUTPUT:
  3332                              <1> 	;	inode (or jump to error)
  3333                              <1> 	;	eax (ax) = [ii] = inode number
  3334                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3335                              <1> 	;
  3336                              <1> 	; Modified registers: (eax), ebx, ecx, edx, esi, edi, ebp
  3337                              <1> 	;
  3338                              <1> 	; IREAD	 equ 100h ; read permission flag, owner
  3339                              <1> 	; IWRITE equ 80h  ; write permission flag, owner
  3340                              <1> 	; IEXEC	 equ 40h  ; execute permission flag, owner	 
  3341                              <1> 		
  3342                              <1> 	; 23/03/2021
  3343 000055FF 52                  <1> 	push	edx ; save flag (DX)
  3344                              <1> 	;push	dx  ; save flag (DL)
  3345 00005600 E810FFFFFF          <1> 	call	iget
  3346                              <1> 		; jsr r0,iget / read in i-node for current directory
  3347                              <1> 			    ; / (i-number passed in r1)
  3348                              <1> 	;;mov	cl, [i.flgs]
  3349                              <1> 	;;	; mov i.flgs,r2
  3350                              <1> 	; 23/03/2021
  3351                              <1> 	;mov	cx, [i.iflgs]	
  3352                              <1> 
  3353                              <1> 	;;pop	dx  ; restore flag (DL)
  3354                              <1> 	; 23/03/2021
  3355 00005605 5A                  <1> 	pop	edx ; restore flag (DX)
  3356                              <1> 
  3357                              <1> 	; 28/11/2021 (iget will not return here if there is an error)
  3358                              <1> 	; 31/10/2021
  3359                              <1> 	;jc	short access_5
  3360                              <1> 
  3361                              <1> 	; 31/10/2021
  3362                              <1> 	; Note: If eax input is same with [mnti], 'iget' will change
  3363                              <1> 	; [cdev] to 1 and eax will be 1 (root dir of mounted fs) 
  3364                              <1> 
  3365                              <1> 	; 27/03/2021
  3366                              <1> 	; 23/03/2021
  3367                              <1> 	; (check if it is write permission flag)
  3368 00005606 6681FA8000          <1> 	cmp	dx, 80h ; IWRITE
  3369 0000560B 775E                <1> 	ja	short access_r	; IREAD = 100h (owner)
  3370 0000560D 722B                <1> 	jb	short access_x	; IEXEC = 40h (owner)
  3371                              <1> 	; IWRITE (80h)
  3372                              <1> access_w:
  3373                              <1> 	; 23/03/2021
  3374                              <1> 	; ((ref: Retro UNIX 386 v2, 'ux.s', 'ldrv' structure))
  3375                              <1> 	;mov	bl, [idev]
  3376                              <1> 	;call	getfs
  3377                              <1>  	;movzx	ebx, byte [idev]  ; logical drive number
  3378                              <1> 	;shl	bx, 6 ; * 64	  ; of current inode	
  3379                              <1> 	;add	ebx, ldrvtable	
  3380                              <1> 	;;test	byte [ebx+ldrv.pflags], 01h ; read only fs flag
  3381                              <1> 	;;jz	short access_0
  3382                              <1> 	;; 14/06/2021
  3383                              <1> 	; 14/06/2021
  3384                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3385                              <1> 	;mov	edi, [ebx+ldrv.superblk]
  3386                              <1> 	;test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3387                              <1> 	;jz	short access_0
  3388                              <1> 	; 31/10/2021
  3389 0000560F 803D[8D750000]01    <1> 	cmp	byte [cdev], 1
  3390 00005616 7207                <1> 	jb	short access_7 ; [cdev] = 0
  3391                              <1> 	; [cdev] = 1
  3392                              <1> 	; 28/11/2021
  3393 00005618 BF[60780000]        <1> 	mov	edi, mount ; mounted file system's superblock buffer
  3394 0000561D EB05                <1> 	jmp	short access_8
  3395                              <1> access_7:
  3396                              <1> 	; 28/11/2021
  3397 0000561F BF[58760000]        <1> 	mov	edi, systm ; root file system's superblock buffer
  3398                              <1> access_8:
  3399 00005624 F6476A01            <1> 	test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3400 00005628 7441                <1> 	jz	short access_0
  3401                              <1> 
  3402                              <1> 	; 23/03/2021
  3403                              <1> 	;mov	dword [u.error], ERR_READ_ONLY_FS
  3404                              <1> 	;		; 'read only file system !' error
  3405                              <1> 	;jmp	error
  3406                              <1> 
  3407                              <1> 	; 19/12/2021
  3408 0000562A F605[59710000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  3409 00005631 7438                <1> 	jz	short access_0  ; no, device file
  3410                              <1> 
  3411                              <1> 	; 31/10/2021
  3412 00005633 B81E000000          <1> 	mov	eax, ERR_READ_ONLY_FS
  3413                              <1> 			; 'read only file system !' error
  3414                              <1> 	; 27/03/2021
  3415 00005638 EB27                <1> 	jmp	short access_5
  3416                              <1> 
  3417                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3418                              <1> 
  3419                              <1> 	;mov	dh, [u.uid]
  3420                              <1> 	;cmp	dh, [i.uid]
  3421                              <1> 	;	; cmpb i.uid,u.uid / is user same as owner of file
  3422                              <1> 	;jne	short access_1
  3423                              <1> 		; bne 1f / no, then branch
  3424                              <1> access_x:
  3425                              <1> 	; IEXEC (40h)
  3426                              <1> 	; 27/03/2021
  3427 0000563A 668B1D[58710000]    <1> 	mov	bx, [i.flgs]
  3428 00005641 F6C780              <1> 	test	bh, 80h ; regular file ?
  3429 00005644 7416                <1> 	jz	short access_4 ; not executable file !
  3430 00005646 F6C740              <1> 	test	bh, 40h	; directory ?
  3431 00005649 7511                <1> 	jnz	short access_4 ; not executable file !
  3432 0000564B 668B0D[FE750000]    <1> 	mov	cx, [u.uid]
  3433 00005652 6609C9              <1> 	or	cx, cx
  3434 00005655 7520                <1> 	jnz	short access_3 ; (restricted user)
  3435                              <1> 	; (super user)
  3436                              <1> 	;test	[i.flgs], dl ; execute permission for owner
  3437                              <1> 	;test	byte [i.flgs], 49h ; for owner, group, others
  3438 00005657 F6C349              <1> 	test	bl, 49h ; exec perm for owner, group, others
  3439 0000565A 7549                <1> 	jnz	short access_2
  3440                              <1> access_4:
  3441                              <1> 	; 31/10/2021
  3442 0000565C B816000000          <1> 	mov	eax, ERR_NOT_EXECUTABLE
  3443                              <1> 			; 'not executable file !' error
  3444                              <1> 	; 26/03/2021
  3445                              <1> ;;sysexec_not_exf:
  3446                              <1> ;	mov	dword [u.error], ERR_NOT_EXECUTABLE
  3447                              <1> ;			; 'not executable file !' error
  3448                              <1> ;access_5:
  3449                              <1> ;	jmp	error
  3450                              <1> 	
  3451                              <1> 	; 31/10/2021
  3452                              <1> access_5:
  3453 00005661 A3[20760000]        <1> 	mov	[u.error], eax
  3454 00005666 E9DDE4FFFF          <1> 	jmp	error
  3455                              <1> 
  3456                              <1> access_r:
  3457                              <1> 	; 27/03/2021
  3458                              <1> access_0:
  3459                              <1> 	; 23/03/2021
  3460 0000566B 668B0D[FE750000]    <1> 	mov	cx, [u.uid]
  3461 00005672 6609C9              <1> 	or	cx, cx ; 0 ; root ?
  3462                              <1> 	;jz	short access_2 ; yes
  3463                              <1> 	; 25/12/2021
  3464 00005675 741E                <1> 	jz	short access_1 ; yes
  3465                              <1> access_3:
  3466                              <1> 	; 13/03/2022
  3467 00005677 663B0D[5C710000]    <1> 	cmp	cx, [i.uid] ; owner ?
  3468 0000567E 7415                <1> 	je	short access_1 ; yes
  3469                              <1> 	;; owner ?
  3470 00005680 8A1D[5E710000]      <1> 	mov	bl, [i.gid]
  3471                              <1> 	;cmp	cx, [i.uid]
  3472                              <1> 	;;je	short access_1
  3473                              <1> 	;; 02/05/2021
  3474                              <1> 	;jne	short access_6
  3475                              <1> 	; 13/03/2022
  3476                              <1> 	; same group ?
  3477 00005686 66C1EA03            <1> 	shr	dx, 3
  3478                              <1> 	; check owner's group number/ID
  3479 0000568A 3A1D[02760000]      <1> 	cmp	bl, [u.gid] ; same group number/ID ?
  3480 00005690 7403                <1> 	je	short access_1 ; yes
  3481                              <1> 	; one of others
  3482                              <1> 	;shr	dx, 6
  3483                              <1> 	;jmp	short access_1 ; others
  3484                              <1> 	; 13/03/2022
  3485                              <1> 	; one of others
  3486 00005692 C0EA03              <1> 	shr	dl, 3
  3487                              <1> ;	; 13/03/2022
  3488                              <1> ;	jmp	short access_1 ; others
  3489                              <1> ;access_6:
  3490                              <1> ;	;shr	cl, 2
  3491                              <1> ;	;	; asrb r2 / shift owner read write bits into non owner
  3492                              <1> ;	;	;       ; / read/write bits
  3493                              <1> ;	;	; asrb r2
  3494                              <1> ;
  3495                              <1> ;	; 23/03/2021
  3496                              <1> ;	; same group ?
  3497                              <1> ;	shr	dx, 3
  3498                              <1> ;	;mov	cl, [u.gid]
  3499                              <1> ;	;cmp	cl, [i.gid]
  3500                              <1> ;	;je	short access_1
  3501                              <1> ;	; 02/05/2021
  3502                              <1> ;	cmp	bl, [u.gid]
  3503                              <1> ;	je	short access_1 ; same group, different owner
  3504                              <1> ;
  3505                              <1> ;	; others
  3506                              <1> ;	;shr	dx, 3
  3507                              <1> ;	shr	dl, 3
  3508                              <1> ;	;jmp	short access_1	
  3509                              <1> ;
  3510                              <1> ;;access_1: ; 1:
  3511                              <1> ;	;and	cl, dl
  3512                              <1> ;	;	; bit r2,(r0)+ / test read-write flags against argument
  3513                              <1> ;	;		     ; / in access call
  3514                              <1> ;	;jnz	short access_2
  3515                              <1> ;	;	; bne 1f
  3516                              <1> ;	
  3517                              <1> ;	;or	dh, dh	; super user (root) ?
  3518                              <1> ;	;	; tstb u.uid
  3519                              <1> ;	;jz	short access_2 ; yes, super user
  3520                              <1> ;	;;jnz	error
  3521                              <1> ;	;	; beq 1f
  3522                              <1> ;	;	; jmp error
  3523                              <1> ;	
  3524                              <1> ;	;mov	dword [u.error], ERR_FILE_ACCESS 
  3525                              <1> ;	;		; 'permission denied !' error
  3526                              <1> ;	;jmp	error
  3527                              <1> 
  3528                              <1> access_1:
  3529                              <1> 	; 23/03/2021
  3530 00005695 668515[58710000]    <1> 	test	dx, [i.flgs]
  3531 0000569C 7507                <1> 	jnz	short access_2
  3532                              <1> 
  3533                              <1> 	;; r/w permission error
  3534                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3535                              <1> 	;		; 'permission denied !' error
  3536                              <1> 	;;jmp	error
  3537                              <1> 
  3538                              <1> 	; 31/10/2021
  3539 0000569E B80B000000          <1> 	mov	eax, ERR_FILE_ACCESS 
  3540                              <1> 			; 'permission denied !' error
  3541                              <1> 	; 27/03/2021
  3542 000056A3 EBBC                <1> 	jmp	short access_5
  3543                              <1> 
  3544                              <1> access_2: ; 1:
  3545                              <1> 	;; DL = flags
  3546                              <1> 	;retn
  3547                              <1> 	;	; rts r0
  3548                              <1> 	; 27/03/2021
  3549                              <1> 	; DX = flag (100h-20h-04h or 80h-10h-02h or 40h-08h-01h)
  3550 000056A5 C3                  <1> 	retn
  3551                              <1> 
  3552                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  3553                              <1> %if 0
  3554                              <1> 
  3555                              <1> setimod:
  3556                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3557                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3558                              <1> 	;
  3559                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3560                              <1> 	; the inode has been modified. Also puts the time of modification
  3561                              <1> 	; into the inode.
  3562                              <1> 	;
  3563                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3564                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3565                              <1> 	;
  3566                              <1> 	
  3567                              <1> 	; push 	edx
  3568                              <1> 	push	eax
  3569                              <1> 
  3570                              <1> 	mov 	byte [imod], 1
  3571                              <1> 		; movb $1,imod / set current i-node modified bytes
  3572                              <1> 	; Erdogan Tan 14-7-2012
  3573                              <1> 	call 	epoch
  3574                              <1> 		 ; mov s.time,i.mtim 
  3575                              <1> 			    ; / put present time into file modified time
  3576                              <1> 		 ; mov s.time+2,i.mtim+2
  3577                              <1> 
  3578                              <1> 	mov 	[i.mtim], eax
  3579                              <1> 	
  3580                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3581                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3582                              <1> 	cmp	dword [i.ctim], 0
  3583                              <1> 	jnz	short setimod_ok
  3584                              <1> 
  3585                              <1> 	mov 	[i.ctim], eax
  3586                              <1> 
  3587                              <1> setimod_ok: ; 31/07/2013
  3588                              <1> 	pop	eax
  3589                              <1> 	;pop	edx
  3590                              <1> 	
  3591                              <1> 	retn
  3592                              <1> 		; rts r0
  3593                              <1> %endif
  3594                              <1> 
  3595                              <1> setimod:
  3596                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  3597                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3598                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3599                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3600                              <1> 	;
  3601                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3602                              <1> 	; the inode has been modified. Also puts the time of modification
  3603                              <1> 	; into the inode.
  3604                              <1> 	;
  3605                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3606                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3607                              <1> 	;
  3608                              <1> 
  3609                              <1> 	; Reference:
  3610                              <1> 	; 25/01/2020 - 'UNIXHDCP.ASM', 'setimod' procedure
  3611                              <1> 	;	(Retro UNIX 386 v2 file system installation utility)
  3612                              <1> 
  3613                              <1> 	; 25/05/2020
  3614                              <1> 	;
  3615                              <1> 	; INPUT:
  3616                              <1> 	;	none
  3617                              <1> 	; OUTPUT:
  3618                              <1> 	;	inode times and [imod] will be set
  3619                              <1> 	;	      ([imodx] will be reset)
  3620                              <1> 	;	cf = 0 	
  3621                              <1> 
  3622                              <1> 	; Modified registers: ecx, (edx)?
  3623                              <1> 	
  3624                              <1> 	;push 	edx
  3625 000056A6 50                  <1> 	push	eax
  3626                              <1> 
  3627 000056A7 C605[9E750000]01    <1> 	mov 	byte [imod], 1
  3628                              <1> 		; movb $1,imod / set current i-node modified bytes
  3629                              <1> 
  3630                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3631 000056AE A1[94710000]        <1> 	mov	eax, [i.ctim] ; inode (file) creation time
  3632 000056B3 21C0                <1> 	and	eax, eax
  3633 000056B5 7518                <1> 	jnz	short setimod_4
  3634                              <1> 
  3635                              <1> 	; New file
  3636                              <1> setimod_1:
  3637                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 by Erdogan Tan
  3638                              <1> 	;	 (Modified UNIX v7 inode and new FS construction) 	
  3639                              <1> 	;
  3640 000056B7 E8AA0C0000          <1> 	call	get_system_time ; get current (unix epoch) time
  3641                              <1> 
  3642                              <1> 	;; Erdogan Tan 14-7-2012
  3643                              <1> 	;call 	epoch
  3644                              <1> 	;	 ; mov s.time,i.mtim 
  3645                              <1> 	;		    ; / put present time into file modified time
  3646                              <1> 	;	 ; mov s.time+2,i.mtim+2
  3647                              <1> 	;
  3648                              <1> 	;mov 	[i.mtim], eax
  3649                              <1> 
  3650                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3651                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3652                              <1> 	;cmp	dword [i.ctim], 0
  3653                              <1> 	;jnz	short setimod_ok
  3654                              <1> 		
  3655 000056BC A3[94710000]        <1> 	mov 	[i.ctim], eax
  3656                              <1> 	
  3657                              <1> 	; 25/05/2020
  3658 000056C1 EB05                <1> 	jmp	short setimod_3
  3659                              <1> 
  3660                              <1> setimod_2:
  3661                              <1> 	; File/Directory data (file size or content) is changed
  3662                              <1> 	; This is last modification date&time
  3663 000056C3 A3[90710000]        <1> 	mov	[i.mtim], eax
  3664                              <1> setimod_3:
  3665                              <1> 	; 19/09/2019 ('UNIXHDCP.ASM', 'setimod' by Erdogan Tan)
  3666                              <1> 	; This is last access or last changing date&time
  3667                              <1> 	; of inode (chmod,chown,chgrp,link)
  3668                              <1> 	; parameters (without file/dir data changing)
  3669 000056C8 A3[8C710000]        <1> 	mov	[i.atim], eax
  3670                              <1> 
  3671                              <1> setimod_ok: ; 31/07/2013
  3672 000056CD 58                  <1> 	pop	eax
  3673                              <1> 	;pop	edx
  3674                              <1> 	
  3675 000056CE C3                  <1> 	retn
  3676                              <1> 		; rts r0
  3677                              <1> setimod_4:
  3678                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3679 000056CF 31C9                <1> 	xor	ecx, ecx
  3680 000056D1 390D[90710000]      <1> 	cmp	[i.mtim], ecx ; 0
  3681 000056D7 76EA                <1> 	jna	short setimod_2
  3682                              <1> 
  3683 000056D9 E8880C0000          <1> 	call	get_system_time ; get current (unix epoch) time
  3684                              <1> 	; ((system time will be updated directly by timer interrupt))
  3685                              <1> 
  3686 000056DE 803D[9F750000]00    <1> 	cmp	byte [imodx], 0 ; flag means "file/dir data is same but
  3687 000056E5 76DC                <1> 	jna	short setimod_2 ; inode has been changed"
  3688                              <1> 
  3689                              <1> 	; File/Dir data (File size or content) is same but
  3690                              <1> 	; inode's mode, link count, owner or group id has been changed
  3691                              <1> 	; (so, we do not change last modification date&time)
  3692 000056E7 C605[9F750000]00    <1> 	mov	byte [imodx], 0 ; reset inode modified (extended) flag
  3693 000056EE EBD8                <1> 	jmp	short setimod_3
  3694                              <1> 
  3695                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  3696                              <1> %if 0
  3697                              <1> 	; Retro UNIX 386 v1.1 'itrunc' code
  3698                              <1> itrunc:
  3699                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3700                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  3701                              <1> 	;
  3702                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3703                              <1> 	;  to zero length.
  3704                              <1> 	;
  3705                              <1> 	; INPUTS ->
  3706                              <1> 	;    r1 - i-number of i-node
  3707                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  3708                              <1> 	;    i.flgs - large file flag		
  3709                              <1> 	;    i.size - size of file	
  3710                              <1> 	; 	 
  3711                              <1> 	; OUTPUTS ->
  3712                              <1> 	;    i.flgs - large file flag is cleared
  3713                              <1> 	;    i.size - set to 0	
  3714                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  3715                              <1> 	;    setimod - set to indicate i-node has been modified
  3716                              <1> 	;    r1 - i-number of i-node  					
  3717                              <1> 	;
  3718                              <1> 	; ((AX = R1)) input/output
  3719                              <1> 	;
  3720                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  3721                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3722                              <1> 
  3723                              <1> 	call	iget
  3724                              <1> 		; jsr r0,iget
  3725                              <1> 	mov	esi, i.dskp
  3726                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  3727                              <1> 	xor	eax, eax
  3728                              <1> itrunc_1: ; 1:
  3729                              <1> 	lodsw
  3730                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  3731                              <1> 	or 	ax, ax
  3732                              <1> 	jz	short itrunc_5
  3733                              <1> 		; beq 5f
  3734                              <1> 	push	esi
  3735                              <1> 		; mov r2,-(sp)
  3736                              <1> 	test    word [i.flgs], 1000h    
  3737                              <1> 		; bit $10000,i.flgs / test large file bit?
  3738                              <1> 	jz	short itrunc_4
  3739                              <1> 		; beq 4f / if clear, branch
  3740                              <1> 	push	eax
  3741                              <1> 		; mov r1,-(sp) / save block number of indirect block
  3742                              <1> 	call	dskrd
  3743                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  3744                              <1> 			     ; / pointed to by r5
  3745                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  3746                              <1> 	mov	ecx, 256
  3747                              <1> 		; mov $256.,r3 / move word count into r3
  3748                              <1> 	mov	esi, ebx
  3749                              <1> itrunc_2: ; 2:
  3750                              <1> 	lodsw
  3751                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  3752                              <1> 			     ; / physical block number
  3753                              <1> 	and	ax, ax
  3754                              <1> 	jz	short itrunc_3
  3755                              <1> 		; beq 3f / branch if zero
  3756                              <1> 	;push	ecx
  3757                              <1> 	push	cx
  3758                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3759                              <1> 	;push	esi
  3760                              <1> 		; mov r5,-(sp)
  3761                              <1> 	call	free
  3762                              <1> 		; jsr r0,free / free block in free storage map
  3763                              <1> 	;pop	esi
  3764                              <1> 		; mov(sp)+,r5
  3765                              <1> 	pop	cx
  3766                              <1> 	;pop	ecx
  3767                              <1> 		; mov (sp)+,r3
  3768                              <1> itrunc_3: ; 3:
  3769                              <1> 	loop	itrunc_2
  3770                              <1> 		; dec r3 / decrement word count
  3771                              <1> 		; bgt 2b / branch if positive
  3772                              <1> 	pop	eax
  3773                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3774                              <1> 			     ; / indirect block
  3775                              <1> 	; 01/08/2013
  3776                              <1>         and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3777                              <1> itrunc_4: ; 4:
  3778                              <1> 	call	free
  3779                              <1> 		; jsr r0,free / free indirect block
  3780                              <1> 	pop	esi
  3781                              <1> 		; mov (sp)+,r2
  3782                              <1> itrunc_5: ; 5:
  3783                              <1> 	cmp	esi, i.dskp+16
  3784                              <1> 		; cmp r2,$i.dskp+16.
  3785                              <1> 	jb	short itrunc_1	
  3786                              <1> 		; bne 1b / branch until all i.dskp entries check
  3787                              <1> 	; 01/08/2013
  3788                              <1> 	;and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3789                              <1> 		; bic $10000,i.flgs / clear large file bit
  3790                              <1> 	mov	edi, i.dskp
  3791                              <1> 	mov	cx, 8
  3792                              <1> 	xor 	ax, ax
  3793                              <1> 	mov	[i.size], ax ; 0
  3794                              <1> 		; clr i.size / zero file size
  3795                              <1> 	rep	stosw
  3796                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3797                              <1> 			   ; / zero block pointers
  3798                              <1> 	call	setimod
  3799                              <1> 		; jsr r0,setimod / set i-node modified flag
  3800                              <1> 	mov	ax, [ii]
  3801                              <1> 		; mov ii,r1
  3802                              <1> 	retn
  3803                              <1> 		; rts r0
  3804                              <1> 
  3805                              <1> 	; Retro UNIX 386 v1.1 'imap' code
  3806                              <1> imap:
  3807                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3808                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3809                              <1> 	;
  3810                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3811                              <1> 	; allocation bit for an i-node whose number in r1.
  3812                              <1> 	;
  3813                              <1> 	; INPUTS ->
  3814                              <1> 	;    r1 - contains an i-number
  3815                              <1> 	;    fsp - start of table containing open files
  3816                              <1> 	;
  3817                              <1> 	; OUTPUTS ->
  3818                              <1> 	;    r2 - byte address of byte with the allocation bit
  3819                              <1> 	;    mq - a mask to locate the bit position.	
  3820                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3821                              <1> 	;
  3822                              <1> 	; ((AX = R1)) input/output
  3823                              <1> 	; ((DL/DX = MQ)) output
  3824                              <1> 	; ((BX = R2)) output
  3825                              <1> 	;
  3826                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3827                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3828                              <1> 	;
  3829                              <1> 		; / get the byte that has the allocation bit for 
  3830                              <1> 		; / the i-number contained in r1
  3831                              <1> 	;mov	dx, 1
  3832                              <1> 	mov	dl, 1
  3833                              <1> 		; mov $1,mq / put 1 in the mq
  3834                              <1> 	movzx	ebx, ax
  3835                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3836                              <1>  		          ; / in the map we must find
  3837                              <1> 	sub	bx, 41
  3838                              <1> 		; sub $41.,r2 / r2 has i-41
  3839                              <1> 	mov	cl, bl
  3840                              <1> 		; mov r2,r3 / r3 has i-41
  3841                              <1> 	and	cl, 7
  3842                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3843                              <1> 			   ; / the bit position
  3844                              <1> 	jz	short imap1
  3845                              <1> 	;shl	dx, cl
  3846                              <1> 	shl	dl, cl
  3847                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3848                              <1> imap1:			   ; / to the left to mask the correct bit
  3849                              <1> 	shr	bx, 3
  3850                              <1> 		; asr r2
  3851                              <1> 		; asr r2
  3852                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3853                              <1> 		       ; / from the start of the map
  3854                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3855                              <1> 	mov	esi, systm
  3856                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3857                              <1> 				; / the super block for drum
  3858                              <1> 	;cmp	word [cdev], 0
  3859                              <1> 	cmp	byte [cdev], 0
  3860                              <1> 		; tst cdev / is the device the disk
  3861                              <1> 	jna	short imap2
  3862                              <1> 		; beq 1f / yes
  3863                              <1> 	add	esi, mount - systm
  3864                              <1> 		; add $mount-systm,r2 / for mounted device,
  3865                              <1> 			; / r2 points to 1st word of its super block
  3866                              <1> imap2: ; 1:
  3867                              <1> 	add	bx, [esi] ;; add free map size to si
  3868                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3869                              <1> 	add	bx, 4
  3870                              <1> 	add	ebx, esi
  3871                              <1>         	; add (sp)+,r2 / ?
  3872                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3873                              <1> 		      ;; (2 + free map size + 2)
  3874                              <1> 		; add $2,r2 / ?
  3875                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3876                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3877                              <1> 	retn
  3878                              <1> 		; rts r0
  3879                              <1> %endif
  3880                              <1> 
  3881                              <1> 	; Retro UNIX 386 v2.0 'itrunc' code
  3882                              <1> itrunc:
  3883                              <1> 	; 26/03/2022
  3884                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  3885                              <1> 	; 07/06/2020
  3886                              <1> 	; 02/06/2020
  3887                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3888                              <1> 	;
  3889                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3890                              <1> 	;  to zero length.
  3891                              <1> 	; 07/06/2020
  3892                              <1> 	; 02/06/2020
  3893                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3894                              <1> 	;
  3895                              <1> 	; 'itrunc' truncates a file whose i-number is given
  3896                              <1> 	; in ax to zero length.
  3897                              <1> 	;
  3898                              <1> 
  3899                              <1> 	; Reference: 
  3900                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  3901                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'itrunc' procedure
  3902                              <1> 
  3903                              <1> 	; * Free all the disk blocks associated
  3904                              <1> 	; * with the specified inode structure.
  3905                              <1> 	
  3906                              <1> 	; INPUT: 
  3907                              <1> 	;	(e)ax = inode number
  3908                              <1> 	; OUTPUT: 
  3909                              <1> 	;	inode will be modified (file size = 0)
  3910                              <1> 	;	; 26/03/20221
  3911                              <1> 	;	eax = 0 (if cf=0)
  3912                              <1> 
  3913                              <1> 	; (Modified registers: eax, edx, ecx, ebx, esi, edi, ebp) 
  3914                              <1> 
  3915                              <1> 	; 07/06/2020
  3916                              <1> 
  3917                              <1> 	; [cdev] = current logical drive number
  3918                              <1> 	;    eax = inode number (for [cdev])
  3919                              <1> 
  3920 000056F0 E820FEFFFF          <1> 	call 	iget
  3921                              <1> 	; 10/01/2022
  3922                              <1> 	;jc	short itrunc_0 ; error code in eax (al)
  3923                              <1> 
  3924                              <1> 	;    eax = inode number, [ii]
  3925                              <1> 	; [cdev] = current logical drive number (same with input)
  3926                              <1> 	; [idev] = logical drive number of current inode, [ii]
  3927                              <1> 	;   [ii] = current inode ([ii] = ax input, if ax was not zero)
  3928                              <1> 	; [imod] = 0		
  3929                              <1> 	; ([imodx] = 0)
  3930                              <1> 
  3931 000056F5 F605[59710000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file or directory	
  3932 000056FC 750F                <1> 	jnz	short itrunc_1
  3933                              <1> 
  3934                              <1> 	; 10/01/2022
  3935 000056FE C705[20760000]FF00- <1> 	mov	dword [u.error], ERR_NOT_REGULAR ; 255 
  3935 00005706 0000                <1>
  3936                              <1> 			; 'not a regular file (or directory) !' error
  3937                              <1> itrunc_0:
  3938 00005708 E93BE4FFFF          <1> 	jmp	error
  3939                              <1> itrunc_1:
  3940 0000570D F605[59710000]10    <1> 	test	byte [i.flgs+1], 10h ; large file (indirect blocks)
  3941 00005714 7528                <1> 	jnz	short itrunc_5 ; large file
  3942 00005716 BE[64710000]        <1> 	mov	esi, i.dskp ; disk address pointer 0
  3943                              <1> itrunc_2:
  3944 0000571B AD                  <1> 	lodsd
  3945 0000571C 21C0                <1> 	and	eax, eax
  3946 0000571E 740C                <1> 	jz	short itrunc_3 ; empty ! (no more sectors/blocks)
  3947                              <1> 	; eax = block address to be released
  3948 00005720 56                  <1> 	push	esi ; * ; 10/01/2022
  3949 00005721 E83FFDFFFF          <1> 	call	free
  3950                              <1> 	; modified registers: ebx, ecx, edx, esi, edi, ebp 
  3951                              <1> 	; 10/01/2022
  3952                              <1> 	;jc	short itrunc_0 ; error code in eax
  3953 00005726 5E                  <1> 	pop	esi ; * ; 10/01/2022
  3954 00005727 31C0                <1> 	xor	eax, eax ; 0
  3955 00005729 8946FC              <1> 	mov	[esi-4], eax ; 0
  3956                              <1> itrunc_3:
  3957 0000572C 81FE[8C710000]      <1> 	cmp	esi, i.dskp+40
  3958 00005732 72E7                <1> 	jb	short itrunc_2 ; next disk address ptr
  3959                              <1> itrunc_4:
  3960 00005734 A3[60710000]        <1> 	mov	[i.size], eax ; 0
  3961                              <1> 	;mov	[i.size_h], al ; 0
  3962                              <1> 	
  3963                              <1> 	; clear large file flag
  3964                              <1> 	;and     byte [i.flgs+1], 0EFh ; 11101111b ; not 10h
  3965                              <1> 		
  3966                              <1> 	;call	setimod
  3967                              <1> 	;retn
  3968 00005739 E968FFFFFF          <1> 	jmp	setimod
  3969                              <1> 
  3970                              <1> itrunc_5:
  3971                              <1> 	; free disk blocks by using triple indirect blocks at first
  3972 0000573E BE[88710000]        <1> 	mov	esi, i.dskp+36
  3973 00005743 8B06                <1> 	mov	eax, [esi]
  3974 00005745 09C0                <1> 	or	eax, eax
  3975 00005747 740C                <1> 	jz	short itrunc_6
  3976                              <1> 
  3977 00005749 BA02000000          <1> 	mov	edx, 2 ; Triple indirect sign (level = 2)
  3978 0000574E E835000000          <1> 	call	tloop
  3979                              <1> 	; 10/01/2022
  3980                              <1> 	;jc	short itrunc_0
  3981                              <1> 		; eax = 0	
  3982 00005753 8906                <1> 	mov	[esi], eax ; 0
  3983                              <1> itrunc_6:
  3984                              <1> 	; free disk blocks by using double indirect blocks at second
  3985 00005755 BE[84710000]        <1> 	mov	esi, i.dskp+32
  3986 0000575A 8B06                <1> 	mov	eax, [esi]
  3987 0000575C 21C0                <1> 	and	eax, eax 
  3988 0000575E 740C                <1> 	jz	short itrunc_7
  3989                              <1> 
  3990 00005760 BA01000000          <1> 	mov	edx, 1 ; Double indirect sign (level = 1)
  3991 00005765 E81E000000          <1> 	call	tloop
  3992                              <1> 	; 10/01/2022
  3993                              <1> 	;jc	short itrunc_0
  3994                              <1> 		; eax = 0	
  3995 0000576A 8906                <1> 	mov	[esi], eax ; 0
  3996                              <1> 	;esi = i.dskp+32
  3997                              <1> itrunc_7:
  3998                              <1> 	; free disk blocks by using single indirect blocks at third
  3999 0000576C 83EE04              <1> 	sub	esi, 4
  4000 0000576F 8B06                <1> 	mov	eax, [esi]
  4001 00005771 09C0                <1> 	or	eax, eax
  4002 00005773 7409                <1> 	jz	short itrunc_8
  4003                              <1> 
  4004 00005775 29D2                <1> 	sub	edx, edx ; 0  ; Single indirect sign (level = 0)
  4005 00005777 E80C000000          <1> 	call	tloop
  4006                              <1> 	; 10/01/2022
  4007                              <1> 	;jc	short itrunc_0
  4008                              <1> 		; eax = 0
  4009 0000577C 8906                <1> 	mov	[esi], eax ; 0
  4010                              <1> itrunc_8:
  4011 0000577E 81FE[64710000]      <1> 	cmp	esi, i.dskp
  4012 00005784 77E6                <1> 	ja	short itrunc_7
  4013 00005786 EBAC                <1> 	jmp	short itrunc_4
  4014                              <1> 
  4015                              <1> tloop:
  4016                              <1> 	; 26/03/2022
  4017                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  4018                              <1> 	; 07/06/2020
  4019                              <1> 	; 03/06/2020
  4020                              <1> 	; 02/06/2020
  4021                              <1> 	; 26/05/2020 - Retro UNIX 386 v2 by Erdogan Tan
  4022                              <1> 	; 
  4023                              <1> 	; * Free all the disk blocks associated
  4024                              <1> 	; * with the specified inode structure.
  4025                              <1> 
  4026                              <1> 	; Reference: 
  4027                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  4028                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'tloop' procedure
  4029                              <1> 
  4030                              <1> 	; INPUT: 
  4031                              <1> 	;	03/06/2020
  4032                              <1> 	;	eax = indirect block number/address (logical)
  4033                              <1> 	;	edx = level (in dl) 
  4034                              <1> 	;	(0 = indirect, 1 = double indr. 2 = triple indr.) 	
  4035                              <1> 	;
  4036                              <1> 	; OUTPUT: 
  4037                              <1> 	;	indirect blocks will be released
  4038                              <1> 	;
  4039                              <1> 	; Modified registers: eax, ebx, ecx, edx
  4040                              <1> 
  4041                              <1> 	; 03/06/2020
  4042                              <1> 
  4043 00005788 57                  <1> 	push	edi ; *
  4044 00005789 56                  <1> 	push	esi ; **
  4045                              <1> 
  4046 0000578A 50                  <1> 	push	eax ; ***
  4047                              <1> 
  4048 0000578B 52                  <1> 	push	edx ; **** level
  4049                              <1> 
  4050                              <1> 	; [ii] = current inode number
  4051                              <1> 	;;[idev] = logical drive number of current inode, [ii]
  4052                              <1> 	; eax = logical sector/block number
  4053                              <1> 
  4054                              <1> 	; 26/03/2022
  4055                              <1> 	; [cdev] = logical drive number (0 or 1)
  4056                              <1> 
  4057                              <1> 	; 10/01/2022
  4058                              <1> 	; convert to physical sector/block number/address
  4059 0000578C E855FAFFFF          <1> 	call	mget_2	
  4060                              <1> 
  4061 00005791 E87A0A0000          <1> 	call	dskrd ; read disk sector
  4062                              <1> 
  4063                              <1> 		;; ebx = buffer header address
  4064                              <1> 		;; eax = physical sector/block number 
  4065                              <1> 		;; [pdn] = phsysical drive (index) number
  4066                              <1> 		
  4067                              <1> 		;; Modified registers: eax, edx, ecx, esi, edi
  4068                              <1> 		;; If cf = 1 --> eax = error code (al)
  4069                              <1> 
  4070                              <1> 	; 10/01/2022
  4071                              <1> 	; Return from 'dskrd': (Retro UNIX 386 v1.2)
  4072                              <1> 	; 	eax = physical block/sector number
  4073                              <1> 	; 	ebx = buffer data address
  4074                              <1>  	; Modified registers: edx, ecx, ebx, esi, edi, ebp
  4075                              <1>  
  4076 00005796 5A                  <1> 	pop	edx ; **** ; level in dl
  4077                              <1> 	; 10/01/2022
  4078                              <1> 	;jc	short tloop_5
  4079                              <1> 
  4080                              <1> 	;mov	esi, [ebx+bufhdr.address] ; buffer address
  4081                              <1> 	; 10/01/2022
  4082 00005797 89DE                <1> 	mov	esi, ebx ; buffer data address	
  4083                              <1> 
  4084                              <1> 	; 07/06/2020
  4085 00005799 B980000000          <1> 	mov	ecx, 512/4 ; 128 dwords	
  4086                              <1> 
  4087 0000579E 80FA01              <1> 	cmp	dl, 1 ; -
  4088 000057A1 722C                <1> 	jb	short tloop_7
  4089 000057A3 7407                <1> 	je	short tloop_1
  4090 000057A5 BF[687E0000]        <1> 	mov	edi, trpi_buf ; triple indirect buffer address
  4091 000057AA EB05                <1> 	jmp	short tloop_2
  4092                              <1> tloop_1:
  4093 000057AC BF[687C0000]        <1> 	mov	edi, dbli_buf ; double indirect buffer address
  4094                              <1> tloop_2:
  4095                              <1> 	; copy disk r/w buffer content to indirect block buffer
  4096                              <1> 	;mov	ecx, 512/4 ; 128 dwords	
  4097 000057B1 F3A5                <1> 	rep	movsd
  4098                              <1> 
  4099 000057B3 FECA                <1> 	dec	dl ; -
  4100                              <1> 		   ; next indirect block level, 2 -> 1, 1 -> 0
  4101 000057B5 89FE                <1> 	mov	esi, edi  ; (dbli, trpi) indirect buffer + 512
  4102 000057B7 B180                <1> 	mov	cl, 128 ; 128 dwords
  4103                              <1> tloop_3:
  4104 000057B9 83EE04              <1> 	sub	esi, 4  ; previous pointer
  4105                              <1> 
  4106 000057BC 8B06                <1> 	mov	eax, [esi]
  4107                              <1> 
  4108 000057BE 09C0                <1> 	or	eax, eax ; 0
  4109 000057C0 7409                <1> 	jz	short tloop_4
  4110                              <1> 
  4111                              <1> 	; 26/03/2022
  4112 000057C2 52                  <1> 	push	edx ; @@
  4113                              <1> 	; 03/06/2020
  4114 000057C3 51                  <1> 	push	ecx ; @
  4115 000057C4 E8BFFFFFFF          <1> 	call	tloop
  4116 000057C9 59                  <1> 	pop	ecx ; @
  4117                              <1> 	; 26/03/2022
  4118 000057CA 5A                  <1> 	pop	edx ; @@
  4119                              <1> 	; 10/01/2022
  4120                              <1> 	;jc	short tloop_5
  4121                              <1> tloop_4:
  4122 000057CB E2EC                <1> 	loop	tloop_3
  4123                              <1> 
  4124 000057CD EB1A                <1> 	jmp	short tloop_10
  4125                              <1> 
  4126                              <1> 	; 10/01/2022
  4127                              <1> ;tloop_5:
  4128                              <1> ;	pop	edx ; ***  ; discard eax
  4129                              <1> ;	; error code in eax
  4130                              <1> ;tloop_6:
  4131                              <1> ;	pop	esi ; **
  4132                              <1> ;	pop	edi ; *
  4133                              <1> ;	retn
  4134                              <1> 	
  4135                              <1> 	; free blocks in current indirect block
  4136                              <1> tloop_7:
  4137                              <1> 	;mov	ecx, 512/4  ; 128 dwords
  4138 000057CF 81C6FC010000        <1> 	add	esi, 508
  4139                              <1> tloop_8:
  4140 000057D5 8B06                <1> 	mov	eax, [esi]
  4141 000057D7 21C0                <1> 	and	eax, eax ; 0 ?
  4142 000057D9 7409                <1> 	jz	short tloop_9
  4143                              <1> 	
  4144 000057DB 56                  <1> 	push	esi ; **** ; 10/01/2022
  4145 000057DC 51                  <1> 	push	ecx ; *****
  4146 000057DD E883FCFFFF          <1> 	call	free
  4147                              <1> 		; if cf = 0 -> eax = 0
  4148                              <1> 		; if cf = 1 -> eax = error code (in al)
  4149 000057E2 59                  <1> 	pop	ecx ; *****
  4150 000057E3 5E                  <1> 	pop	esi ; **** ; 10/01/2022
  4151                              <1> 	; 10/01/2022
  4152                              <1> 	;; 07/06/2020
  4153                              <1> 	;jc	short tloop_6
  4154                              <1> tloop_9:
  4155 000057E4 83EE04              <1> 	sub	esi, 4
  4156 000057E7 E2EC                <1> 	loop	tloop_8
  4157                              <1> tloop_10:
  4158 000057E9 58                  <1> 	pop	eax ; *** ; free indirect block's itself
  4159 000057EA E876FCFFFF          <1> 	call	free
  4160                              <1> 		;; if cf = 0 -> eax = 0
  4161                              <1> 		;; if cf = 1 -> eax = error code (in al)
  4162                              <1> 	; 10/01/2022
  4163                              <1> 	; (if we are here, there is not an error, cf=0) 
  4164                              <1> 	;jmp	short tloop_6
  4165                              <1> 
  4166                              <1> 	; 10/02/2022
  4167 000057EF 31C0                <1> 	xor	eax, eax ; 0
  4168 000057F1 5E                  <1> 	pop	esi ; **
  4169 000057F2 5F                  <1> 	pop	edi ; *
  4170 000057F3 C3                  <1> 	retn
  4171                              <1> 
  4172                              <1> 	; Retro UNIX 386 v2.0 'imap' code
  4173                              <1> 	;	(runix v2 fs inode map)
  4174                              <1> imap:
  4175                              <1> 	; 26/03/2022
  4176                              <1> 	; 12/03/2022
  4177                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  4178                              <1> 	;	(major modification)
  4179                              <1> 	; 05/11/2021 - temporary (simplified code)
  4180                              <1> 	; 21/08/2021
  4181                              <1> 	; 15/08/2021
  4182                              <1> 	; 14/06/2021
  4183                              <1> 	; 02/05/2021
  4184                              <1> 	; 01/04/2021, 08/04/2021, 24/04/2021
  4185                              <1> 	; 29/03/2021
  4186                              <1> 	; 28/03/2021 - Retro UNIX 386 v2 (beginning)
  4187                              <1> 	;
  4188                              <1> 	; 'imap' finds the byte in inode map containing
  4189                              <1> 	; allocation bit for an i-node whose number in (E)AX
  4190                              <1> 	;
  4191                              <1> 	; (ref: 'UNIXHDCP.ASM', imap', 22/01/2020) 
  4192                              <1> 	;
  4193                              <1> 	; ((Retro UNIX 386 v2 'imap' code is mostly different
  4194                              <1> 	; than Retro UNIX 386 v1.1 'imap' code.))
  4195                              <1> 	;
  4196                              <1> 	; INPUTS ->
  4197                              <1> 	;   EAX = inode number
  4198                              <1> 	;        0 = first free inode
  4199                              <1> 	;       >0 = requested inode
  4200                              <1> 	;   [cdev] = current (logical) drive/device
  4201                              <1> 	;	
  4202                              <1> 	; OUTPUTS ->
  4203                              <1> 	;    EBX = address of the byte contains allocation bit
  4204                              <1> 	;     DX has 1 at calculated bit position
  4205                              <1> 	;   ; 05/11/2021	
  4206                              <1> 	;    EBP = superblock buffer address  
  4207                              <1> 	;    (EAX = inode number)
  4208                              <1> 	;   12/03/2022
  4209                              <1> 	;    (if EAX input is 0, EAX = first free inode > 1)
  4210                              <1> 	;	 		  	
  4211                              <1> 	;   ; 08/04/2021
  4212                              <1> 	;     If cf=1 -> error code in eax (al) 	
  4213                              <1> 	;
  4214                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp
  4215                              <1> 
  4216                              <1> 	; 05/11/2021
  4217 000057F4 803D[8D750000]00    <1> 	cmp	byte [cdev], 0
  4218 000057FB 7616                <1> 	jna	short imap_0
  4219                              <1> 	; 10/01/2022
  4220 000057FD BD[60780000]        <1> 	mov	ebp, mount ; mounted fs superblock buffer
  4221 00005802 EB14                <1> 	jmp	short imap_1
  4222                              <1> 
  4223                              <1> imap_ialloc_err:
  4224                              <1> 	; 10/01/2022
  4225 00005804 C705[20760000]2100- <1> 	mov	dword [u.error], ERR_INO_ALLOC ; 33
  4225 0000580C 0000                <1>
  4226                              <1> 			; 'inode allocation error !'
  4227 0000580E E935E3FFFF          <1> 	jmp	error
  4228                              <1>  
  4229                              <1> imap_0:
  4230                              <1> 	; 10/01/2022
  4231 00005813 BD[58760000]        <1> 	mov	ebp, systm ; root fs superblock buffer
  4232                              <1> imap_1:
  4233                              <1> 	; 26/03/2022
  4234                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4235                              <1> imap_x:
  4236                              <1> 	; 05/11/2021
  4237                              <1> 	; 21/08/2021
  4238                              <1> 	; 15/08/2021 (Retro UNIX 386 v2)
  4239                              <1> 	; call from 'maknod2' ; 10/01/2022
  4240                              <1> 	;
  4241                              <1> 	; eax = inode number
  4242                              <1> 	; [cdev] = device number for inode in eax
  4243                              <1> 	; ebp = superblock buffer address
  4244                              <1> 
  4245                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4246                              <1> 	; 'imap' and 'imap_x' will return with..
  4247                              <1> 	;    ECX = byte offset from inode map buff (imap_x)
  4248                              <1> 	;    EBX = byte addr of the byte with allocation bit
  4249                              <1> 	;    EDX (DL) has a 1 in the calculated bit position
  4250                              <1> 
  4251                              <1> 	; 02/05/2021
  4252                              <1> 	; convert inode number to first free inode if it is 0
  4253 00005818 E83B000000          <1> 	call	imap_3 ; 10/01/2022
  4254 0000581D 72E5                <1> 	jc	short imap_ialloc_err
  4255                              <1> 	; eax = inode number > 1 (1 = root directory inode)
  4256                              <1> 
  4257 0000581F 898584000000        <1> 	mov	[ebp+SB.LastInode], eax
  4258                              <1> 	
  4259 00005825 50                  <1> 	push	eax ; * ; save inode number
  4260                              <1> 
  4261                              <1> 	; convert inode number to inode map sector index
  4262 00005826 E845000000          <1> 	call	imap_8 ; 10/01/2022
  4263 0000582B 50                  <1> 	push	eax ; ** ; byte offset in inode map buffer
  4264                              <1> 
  4265                              <1> 	; edx = inode map buffer sector index number (< 16)
  4266                              <1> 	; eax = byte offset in inode map buffer (< 512)
  4267                              <1> 
  4268                              <1> 	; 15/08/2021
  4269 0000582C 89958C000000        <1> 	mov	[ebp+SB.ImapIndex], edx
  4270 00005832 8B4520              <1> 	mov	eax, [ebp+SB.InodeMapAddr]
  4271 00005835 01D0                <1> 	add	eax, edx
  4272 00005837 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  4273                              <1> 	; eax = physical sector number
  4274                              <1> 	; [cdev] = current device/disk number
  4275                              <1> 	
  4276                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4277 0000583A 55                  <1> 	push	ebp ; ***
  4278 0000583B E8D0090000          <1> 	call	dskrd
  4279 00005840 5D                  <1> 	pop	ebp ; ***
  4280                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  4281                              <1> 	; eax = physical sector number
  4282                              <1> 	; ebx = buffer data address
  4283                              <1> 
  4284                              <1> 	; 26/03/2022
  4285                              <1> 	; (ecx may be > 255 at return from dskrd)
  4286                              <1> 	;sub	ecx, ecx ; 0
  4287                              <1> 	; 10/01/2022
  4288 00005841 8A4C2404            <1> 	mov	cl, [esp+4] ; * ; inode number
  4289 00005845 FEC9                <1> 	dec	cl
  4290                              <1> 	; 26/03/2022
  4291 00005847 31D2                <1> 	xor	edx, edx
  4292                              <1> 	;mov	dl, 1
  4293 00005849 FEC2                <1> 	inc	dl ; dl = 1
  4294                              <1> 	;and	ecx, 7
  4295                              <1> 	; 26/03/2022
  4296                              <1> 	; 02/05/2021
  4297                              <1> 	;dec	cl
  4298                              <1> 	;jz	short imap_2 ; 15/08/2021
  4299 0000584B 80E107              <1> 	and	cl, 7	; 1 imap byte is for 8 inodes 
  4300                              <1> 	;jz	short imap_2
  4301 0000584E D2E2                <1> 	shl	dl, cl
  4302                              <1> imap_2:
  4303                              <1> 	; 10/01/2022
  4304                              <1> 	; save physical sector number of imap sector in the SB
  4305 00005850 89457C              <1> 	mov	[ebp+SB.ImapBuffer], eax ; ! sector addr !
  4306                              <1> 	; 
  4307 00005853 59                  <1> 	pop	ecx ; ** ; byte offset in inode map buffer
  4308 00005854 01CB                <1> 	add	ebx, ecx ; + byte position
  4309 00005856 58                  <1> 	pop	eax ; * ; inode number
  4310                              <1> 
  4311                              <1> 	; 10/01/2022
  4312                              <1> 	; ECX contains byte offset from inode map buff (imap_x)
  4313                              <1> 	; EDX (DL) has a 1 in the calculated bit position
  4314                              <1> 	; EBX has byte address of the byte with allocation bit
  4315                              <1> 
  4316 00005857 C3                  <1> 	retn
  4317                              <1> 
  4318                              <1> imap_3:
  4319                              <1> 	; 10/01/2022
  4320                              <1> 	; 15/08/2021
  4321                              <1> 	; 02/05/2021
  4322                              <1> 	; 28/03/2021
  4323                              <1> 	; get first free inode number (from superblock)
  4324                              <1> 	; and check inode number against inode count
  4325                              <1> 	;
  4326                              <1> 	; INPUT:
  4327                              <1> 	;    eax = 0 -> get first free inode number
  4328                              <1> 	;    (eax > 0 -> check inode number)
  4329                              <1> 	;    ebp = superblock address ; 15/08/2021
  4330                              <1> 	; OUTPUT:
  4331                              <1> 	;    eax = inode number 
  4332                              <1> 	;    (eax will be 2 when SB.FirstFreeIno is invalid)
  4333                              <1> 	;    cf = 1 -> inode allocation error/problem
  4334                              <1> 	
  4335 00005858 21C0                <1> 	and	eax, eax	
  4336 0000585A 750E                <1> 	jnz	short imap_5
  4337                              <1> 
  4338                              <1> 	; get first free inode
  4339                              <1> 	;mov	eax, [ebp+SB.FreeInodes]
  4340                              <1> 	;and	eax, eax
  4341                              <1> 	;jz	short imap_6
  4342                              <1> 	; 10/01/2022
  4343 0000585C 394530              <1> 	cmp	[ebp+SB.FreeInodes], eax ; 0
  4344 0000585F 760D                <1> 	jna	short imap_6	
  4345 00005861 8B4534              <1> 	mov	eax, [ebp+SB.FirstFreeIno] ; 1 based inode num
  4346 00005864 40                  <1> 	inc	eax
  4347 00005865 7502                <1> 	jnz	short imap_4 ; 0FFFFFFFFh -> 0
  4348                              <1> 	; invalid first free inode value (not initialized)
  4349 00005867 B003                <1> 	mov	al, 3 ; first free inode to be searched + 1
  4350                              <1> imap_4:
  4351 00005869 48                  <1> 	dec	eax
  4352                              <1> imap_5:
  4353                              <1> 	; 15/08/2021
  4354                              <1> 	; check inode number against inode count of the fs
  4355 0000586A 394514              <1> 	cmp	[ebp+SB.InodeCount], eax
  4356 0000586D C3                  <1> 	retn	; if cf = 1 --> inode number > inode count
  4357                              <1> imap_6:
  4358                              <1> 	; 'imap' inode allocation error !
  4359 0000586E F9                  <1> 	stc
  4360                              <1> imap_7:
  4361 0000586F C3                  <1> 	retn
  4362                              <1> 
  4363                              <1> imap_8:
  4364                              <1> 	; 10/01/2022
  4365                              <1> 	; 15/08/2021
  4366                              <1> 	; 02/05/2021
  4367                              <1> 	; 28/03/2021
  4368                              <1> 	; convert inode count to inode map sector index
  4369                              <1> 	;
  4370                              <1> 	; INPUT: 
  4371                              <1> 	;    eax = inode number
  4372                              <1> 	; OUTPUT:
  4373                              <1> 	;    edx = inode map sector offset/index number
  4374                              <1> 	;    eax = byte offset from start of imapbuf	 
  4375                              <1> 
  4376 00005870 31D2                <1> 	xor	edx, edx
  4377 00005872 48                  <1> 	dec	eax ; zero based inode number
  4378 00005873 74FA                <1> 	jz	short imap_7
  4379                              <1> 
  4380 00005875 C1E803              <1> 	shr	eax, 3 ; 8 inodes per inode map byte
  4381                              <1> 		; eax = byte offset from start of inode map
  4382 00005878 88E2                <1> 	mov	dl, ah ; ah <= 31 (1Fh) for Retro UNIX 386 v2
  4383 0000587A D0EA                <1> 	shr	dl, 1
  4384                              <1> 		; edx = inode map sector offset/index number
  4385                              <1> 	;and	eax, 511
  4386 0000587C 6625FF01            <1> 	and	ax, 511
  4387                              <1> 		; eax = byte offset from start of imapbuf
  4388 00005880 C3                  <1> 	retn
  2092                                  %include 'u6.s'      ; 31/05/2015
  2093                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2094                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2095                              <1> ; ****************************************************************************
  2096                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC
  2097                              <1> ; Last Modification: 09/03/2022
  2098                              <1> ; ----------------------------------------------------------------------------
  2099                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2100                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2101                              <1> ;
  2102                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2103                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2104                              <1> ; <Bell Laboratories (17/3/1972)>
  2105                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2106                              <1> ;
  2107                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2108                              <1> ;
  2109                              <1> ; ****************************************************************************
  2110                              <1> 
  2111                              <1> 	; 09/03/2022
  2112                              <1> 	; 25/12/2021
  2113                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2114                              <1> readi:
  2115                              <1> 	; 20/05/2015
  2116                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2117                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2118                              <1> 	;
  2119                              <1> 	; Reads from an inode whose number in R1
  2120                              <1> 	; 
  2121                              <1> 	; INPUTS ->
  2122                              <1> 	;    r1 - inode number
  2123                              <1> 	;    u.count - byte count user desires
  2124                              <1> 	;    u.base - points to user buffer
  2125                              <1> 	;    u.fofp - points to word with current file offset
  2126                              <1> 	; OUTPUTS ->
  2127                              <1> 	;    u.count - cleared
  2128                              <1> 	;    u.nread - accumulates total bytes passed back
  2129                              <1> 	;
  2130                              <1> 	; ((AX = R1)) input/output
  2131                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2132                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2133                              <1> 
  2134 00005881 31D2                <1> 	xor	edx, edx ; 0
  2135 00005883 8915[D8750000]      <1> 	mov 	[u.nread], edx ; 0
  2136                              <1> 		; clr u.nread / accumulates number of bytes transmitted
  2137 00005889 668915[18760000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2138 00005890 3915[D4750000]      <1> 	cmp 	[u.count], edx ; 0
  2139                              <1> 		; tst u.count / is number of bytes to be read greater than 0
  2140 00005896 7701                <1> 	ja 	short readi_1 ; 1f
  2141                              <1> 		; bgt 1f / yes, branch
  2142 00005898 C3                  <1> 	retn
  2143                              <1> 		; rts r0 / no, nothing to read; return to caller
  2144                              <1> readi_1: ; 1:
  2145                              <1> 	;	; mov r1,-(sp) / save i-number on stack
  2146                              <1> 	;cmp	ax, 40
  2147                              <1> 	;	; cmp r1,$40. / want to read a special file 
  2148                              <1> 	;	;             / (i-nodes 1,...,40 are for special files)
  2149                              <1>         ;ja	dskr 
  2150                              <1> 	;	; ble 1f / yes, branch
  2151                              <1> 	;	; jmp dskr / no, jmp to dskr; 
  2152                              <1> 	;	;         / read file with i-node number (r1)
  2153                              <1> 	;	;    / starting at byte ((u.fofp)), read in u.count bytes
  2154                              <1> 	
  2155                              <1> 	; 28/11/2021
  2156 00005899 F605[1E760000]FF    <1> 	test	byte [u.kcall], 0FFh
  2157                              <1> 	;jnz	short readi_2  ; 'readi' called by 'namei'
  2158                              <1> 	; 09/03/2022
  2159                              <1> 	;jz	short _readi_2
  2160                              <1> 	;jmp	dskr
  2161 000058A0 750C                <1> 	jnz	short readi_2 ; 'readi' called by 'namei'
  2162                              <1> ;_readi_2:	; 09/03/2022
  2163                              <1> 	; eax = inode number
  2164                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2165 000058A2 E86EFCFFFF          <1> 	call	iget
  2166                              <1> ;readi_2:
  2167                              <1> 	; 28/11/2021
  2168                              <1> 	; eax = inode number
  2169                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2170 000058A7 E881040000          <1> 	call	is_regular_file
  2171                              <1> 	;jz	dskr ; regular file 
  2172                              <1> 	; 25/12/2021
  2173 000058AC 7505                <1> 	jnz	short readi_5 ; device file 
  2174                              <1> readi_2:	 ; 09/03/2022
  2175                              <1> 	; regular file
  2176 000058AE E9E3000000          <1> 	jmp	dskr
  2177                              <1> readi_5:
  2178                              <1> 	; (20/05/2015)
  2179 000058B3 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2180                              <1> 
  2181                              <1> 	; 28/11/2021	
  2182                              <1> 	; device file
  2183 000058B4 BB[CE580000]        <1> 	mov	ebx, readi_4
  2184 000058B9 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2185 000058BC 720E                <1> 	jb	short readi_3
  2186 000058BE 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2187 000058C1 7709                <1> 	ja	short readi_3	
  2188                              <1> 	
  2189                              <1> 	; convert v2 inode number to v1 device inode number
  2190 000058C3 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2191 000058C5 89C1                <1> 	mov	ecx, eax
  2192 000058C7 C0E102              <1> 	shl	cl, 2 ; * 4
  2193 000058CA 01CB                <1> 	add	ebx, ecx
  2194                              <1> readi_3:
  2195 000058CC FF23                <1> 	jmp	dword [ebx]	
  2196                              <1> 		 ; jmp *1f-2(r1)
  2197                              <1> readi_4: ; 1:
  2198 000058CE [1E590000]          <1> 	dd	null ; 28/11/2021
  2199 000058D2 [22590000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2200                              <1> 		 ;rtty / tty; r1=2
  2201                              <1> 		 ;rppt / ppt; r1=4
  2202 000058D6 [72590000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2203                              <1> 		 ;rmem / mem; r1=6
  2204                              <1> 		 ;rrf0 / rf0
  2205                              <1> 		 ;rrk0 / rk0
  2206                              <1> 		 ;rtap / tap0
  2207                              <1> 		 ;rtap / tap1
  2208                              <1> 		 ;rtap / tap2
  2209                              <1> 		 ;rtap / tap3
  2210                              <1> 		 ;rtap / tap4
  2211                              <1> 		 ;rtap / tap5
  2212                              <1> 		 ;rtap / tap6
  2213                              <1> 		 ;rtap / tap7
  2214 000058DA [C1600000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2215 000058DE [C1600000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2216 000058E2 [C1600000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2217 000058E6 [C1600000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2218 000058EA [C1600000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2219 000058EE [C1600000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2220 000058F2 [87590000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2221 000058F6 [6E590000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2222                              <1> 		 ;rcvt / tty0
  2223 000058FA [6E590000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2224                              <1> 		 ;rcvt / tty1
  2225 000058FE [6E590000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2226                              <1> 		 ;rcvt / tty2
  2227 00005902 [6E590000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2228                              <1> 		 ;rcvt / tty3
  2229 00005906 [6E590000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2230                              <1> 		 ;rcvt / tty4
  2231 0000590A [6E590000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2232                              <1> 		 ;rcvt / tty5
  2233 0000590E [6E590000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2234                              <1> 		 ;rcvt / tty6
  2235 00005912 [6E590000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2236                              <1> 		 ;rcvt / tty7
  2237 00005916 [6E590000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2238                              <1> 		 ;rcrd / crd
  2239 0000591A [6E590000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2240                              <1> 
  2241                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2242                              <1> null:
  2243 0000591E 31C0                <1> 	xor	eax, eax
  2244 00005920 58                  <1> 	pop	eax
  2245 00005921 C3                  <1> 	retn
  2246                              <1> 
  2247                              <1> 	; 11/01/2022
  2248                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2249                              <1> rtty: ; / read from console tty
  2250                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2251                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2252                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2253                              <1> 	;	     must be written immediate on video page (screen)
  2254                              <1> 	;	     when it is required.	
  2255                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2256                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2257                              <1> 	;
  2258                              <1> 	; Console tty buffer is PC keyboard buffer
  2259                              <1> 	; and keyboard-keystroke handling is different than original
  2260                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2261                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2262                              <1> 	;
  2263                              <1> 	; 06/12/2013
  2264 00005922 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2265 00005929 8A83[D7710000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2266                              <1> rttys:
  2267                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2268                              <1> 	               ; / of the control and status block
  2269                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2270                              <1> 		       ; / tty buffer
  2271                              <1> 	; 28/07/2013
  2272 0000592F A2[E1750000]        <1> 	mov 	[u.ttyn], al
  2273                              <1> 	; 13/01/2014
  2274 00005934 FEC0                <1> 	inc	al
  2275 00005936 A2[E2750000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2276                              <1> rtty_nc: ; 01/02/2014
  2277                              <1> 	; 29/09/2013
  2278                              <1> 	;mov	ecx, 10
  2279                              <1> 	; 11/01/2022
  2280 0000593B 29C9                <1> 	sub	ecx, ecx
  2281 0000593D B10A                <1> 	mov	cl, 10
  2282                              <1> rtty_1: 	; 01/02/2014
  2283                              <1> 	;push 	cx ; 29/09/2013
  2284                              <1> 	; 11/12/2021
  2285 0000593F 51                  <1> 	push	ecx
  2286                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2287 00005940 B001                <1> 	mov 	al, 1
  2288 00005942 E8D10B0000          <1> 	call 	getc
  2289                              <1> 	;pop 	cx ; 29/09/2013	
  2290                              <1> 	; 11/12/2021
  2291 00005947 59                  <1> 	pop	ecx
  2292 00005948 7516                <1> 	jnz	short rtty_2
  2293                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2294                              <1> 	               ; / of chars. Is this number non-zero?
  2295 0000594A E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2296                              <1> 	; 05/10/2013
  2297 0000594C 8A25[E1750000]      <1> 	mov	ah, [u.ttyn]
  2298                              <1> 	; 29/09/2013
  2299 00005952 E8C8F7FFFF          <1> 	call	sleep
  2300                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2301                              <1>                 ;           / (120 chars.)
  2302                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2303 00005957 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2304                              <1> 
  2305                              <1> rtty_idle:
  2306                              <1> 	; 29/07/2013
  2307 00005959 E834F7FFFF          <1> 	call 	idle
  2308 0000595E EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2309                              <1> 	;1:
  2310                              <1> 		; tst 2(r5) / is the number of characters zero
  2311                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2312                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2313                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2314                              <1> 		          ; / contains the next char.
  2315                              <1> 		; dec 2(r5) / decrement the character count
  2316                              <1> rtty_2:
  2317 00005960 30C0                <1> 	xor 	al, al
  2318 00005962 E8B10B0000          <1> 	call 	getc
  2319 00005967 E891000000          <1> 	call	passc
  2320                              <1> 		; jsr r0,passc / move the character to core (user)
  2321                              <1> 	;; 17/10/2015 - 16/07/2015
  2322                              <1> 	; 19/06/2014
  2323                              <1> 	;;jnz	short rtty_nc
  2324 0000596C 58                  <1> 	pop	eax  ; (20/05/2015)
  2325 0000596D C3                  <1> 	retn 
  2326                              <1> ;ret1:
  2327                              <1> 		; jmp ret / return to caller via 'ret'
  2328                              <1> 
  2329                              <1> rcvt:   ; < receive/read character from tty >
  2330                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2331                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2332                              <1> 	;
  2333                              <1> 	; Retro UNIX 8086 v1 modification !
  2334                              <1> 	; 
  2335                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2336                              <1> 	;		(exactly different than this one)
  2337                              <1> 	;	was in 'u9.s' file.
  2338                              <1> 	;
  2339 0000596E 2C0A                <1> 	sub 	al, 10
  2340                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2341                              <1> 	; 16/07/2013
  2342                              <1> 	; 21/05/2013
  2343 00005970 EBBD                <1>         jmp     short rttys
  2344                              <1>       
  2345                              <1> ;rppt: / read paper tape
  2346                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2347                              <1> ;			 / places
  2348                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2349                              <1> ;		       / also enables read bit in prs
  2350                              <1> ;	jsr	r0,passc / place character in users buffer area
  2351                              <1> ;	br	rppt
  2352                              <1> 
  2353                              <1> rmem: ; / transfer characters from memory to a user area of core
  2354                              <1> 	; 17/10/2015
  2355                              <1> 	; 11/06/2015
  2356                              <1> 	; 24/05/2015
  2357                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2358                              <1> 	;
  2359 00005972 8B35[C0750000]      <1> 	mov     esi, [u.fofp]
  2360                              <1> rmem_1:
  2361 00005978 8B1E                <1>         mov     ebx, [esi]        
  2362                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2363                              <1> 		               ; / to be transferred to user
  2364 0000597A FF06                <1>         inc     dword [esi] ; 17/10/2015
  2365                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2366                              <1> 			    ; / char in memory file
  2367 0000597C 8A03                <1> 	mov	al, [ebx]
  2368                              <1> 		; movb (r1),r1 / get character from memory file, 
  2369                              <1> 		             ; / put it in r1
  2370 0000597E E87A000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2371                              <1> 			     ;  / the next byte of the users core area
  2372                              <1> 		; br rmem / continue
  2373 00005983 75F3                <1> 	jnz	short rmem_1
  2374                              <1> ret_:
  2375 00005985 58                  <1> 	pop	eax ; 09/06/2015
  2376 00005986 C3                  <1> 	retn
  2377                              <1> 
  2378                              <1> rlpr:
  2379                              <1> ;1:
  2380                              <1> ;rcrd:
  2381 00005987 C705[20760000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2381 0000598F 0000                <1>
  2382 00005991 E9B2E1FFFF          <1> 	jmp	error
  2383                              <1> 		;jmp	error / see 'error' routine
  2384                              <1> 
  2385                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2386                              <1> dskr:
  2387                              <1> 	; 12/10/2015
  2388                              <1> 	; 21/08/2015
  2389                              <1> 	; 25/07/2015
  2390                              <1> 	; 10/07/2015
  2391                              <1> 	; 16/06/2015
  2392                              <1> 	; 31/05/2015
  2393                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2394                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2395                              <1> dskr_0:
  2396 00005996 50                  <1> 	push	eax
  2397                              <1> 		; mov (sp),r1 / i-number in r1
  2398                              <1> 	; AX = i-number
  2399 00005997 E879FBFFFF          <1> 	call	iget
  2400                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2401                              <1>         ;movzx	edx, word [i.size] ; 16/06/2015
  2402                              <1> 	;	; mov i.size,r2 / file size in bytes in r2
  2403                              <1> 	; 28/11/2021
  2404 0000599C 8B15[60710000]      <1> 	mov	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2405                              <1> 	;
  2406 000059A2 8B1D[C0750000]      <1> 	mov	ebx, [u.fofp]
  2407 000059A8 2B13                <1> 	sub	edx, [ebx]
  2408                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2409                              <1>         ; 12/10/2015
  2410                              <1> 	; jna	short ret_ 
  2411                              <1> 		; blos ret
  2412 000059AA 7709                <1> 	ja	short dskr_1
  2413                              <1> 	;
  2414                              <1> dskr_retn: ; 12/10/2015
  2415 000059AC 58                  <1> 	pop	eax
  2416 000059AD C605[1E760000]00    <1> 	mov	byte [u.kcall], 0
  2417 000059B4 C3                  <1> 	retn	
  2418                              <1> dskr_1: 
  2419 000059B5 3B15[D4750000]      <1> 	cmp     edx, [u.count] 
  2420                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2421                              <1> 			       ; / to carry out read
  2422 000059BB 7306                <1> 	jnb	short dskr_2
  2423                              <1> 		; bhis 1f
  2424 000059BD 8915[D4750000]      <1> 	mov	[u.count], edx
  2425                              <1> 		; mov r2,u.count / no, just read to end of file
  2426                              <1> dskr_2: ; 1:
  2427                              <1> 	; (E)AX = i-number ; 28/11/2021 (32 bit inode number)
  2428                              <1> 	;call	mget
  2429                              <1> 		; jsr r0,mget / returns physical block number of block 
  2430                              <1> 		    ; / in file where offset points
  2431                              <1> 	; 28/11/2021
  2432 000059C3 E8D8F7FFFF          <1> 	call	mget_r
  2433                              <1> 
  2434                              <1> 	; eax = physical block number
  2435                              <1> 	; [cdev] = current device number 
  2436 000059C8 E843080000          <1> 	call	dskrd
  2437                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2438                              <1> 			     ; / 1st word of data in buffer
  2439                              <1> 	; 09/06/2015
  2440 000059CD 803D[1E760000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2441 000059D4 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2442 000059D6 66833D[18760000]00  <1> 	cmp	word [u.pcount], 0
  2443 000059DE 7705                <1> 	ja	short dskr_4
  2444                              <1> dskr_3:
  2445                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2446 000059E0 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2447                              <1> dskr_4:
  2448                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2449 000059E5 E8C2020000          <1> 	call	sioreg
  2450                              <1> 		; jsr r0,sioreg
  2451 000059EA 87F7                <1> 	xchg	esi, edi
  2452                              <1> 	; edi = file (user data) offset
  2453                              <1> 	; edi = sector (I/O) buffer offset
  2454                              <1> 	; ecx = byte count
  2455 000059EC F3A4                <1> 	rep	movsb
  2456                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2457                              <1> 		                 ; / starting at u.base
  2458                              <1> 		; dec r3
  2459                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2460                              <1> 	; 25/07/2015
  2461                              <1> 	; eax = remain bytes in buffer
  2462                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2463 000059EE 09C0                <1> 	or	eax, eax
  2464 000059F0 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2465                              <1> 	; 03/08/2013
  2466                              <1> 	;pop	eax
  2467 000059F2 390D[D4750000]      <1> 	cmp	[u.count], ecx ; 0
  2468                              <1> 		; tst u.count / all bytes read off disk
  2469                              <1> 		; bne dskr
  2470                              <1> 		; br ret
  2471                              <1>         ;ja	short dskr_0
  2472                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2473                              <1> 	;retn
  2474                              <1> 	; 12/10/2015
  2475 000059F8 76B2                <1> 	jna	short dskr_retn
  2476 000059FA 58                  <1> 	pop	eax  ; (i-node number)
  2477 000059FB EB99                <1> 	jmp	short dskr_0
  2478                              <1> 	
  2479                              <1> passc:
  2480                              <1> 	; 18/10/2015
  2481                              <1> 	; 10/07/2015
  2482                              <1> 	; 01/07/2015
  2483                              <1> 	; 08/06/2015
  2484                              <1> 	; 04/06/2015
  2485                              <1> 	; 20/05/2015
  2486                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2487                              <1> 	;
  2488                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2489                              <1> 	;		      to physical address
  2490 000059FD 66833D[18760000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2491                              <1> 			     ; 1-4095 --> use previous physical base address
  2492                              <1> 			     ; in [u.pbase]
  2493 00005A05 7705                <1> 	ja	short passc_3
  2494                              <1> 	; 08/06/2015 - 10/07/2015
  2495 00005A07 E82C000000          <1> 	call	trans_addr_w
  2496                              <1> passc_3:
  2497                              <1> 	; 19/05/2015
  2498 00005A0C 66FF0D[18760000]    <1> 	dec	word [u.pcount]
  2499                              <1> 	;
  2500 00005A13 8B1D[14760000]      <1> 	mov	ebx, [u.pbase]
  2501 00005A19 8803                <1> 	mov	[ebx], al
  2502                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2503                              <1> 		               ; / users buffer
  2504 00005A1B FF05[D0750000]      <1> 	inc	dword [u.base]
  2505                              <1> 		; inc u.base / increment the pointer to point to 
  2506                              <1> 			  ; / the next byte in users buffer
  2507 00005A21 FF05[14760000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2508 00005A27 FF05[D8750000]      <1> 	inc	dword [u.nread]
  2509                              <1> 		; inc u.nread / increment the number of bytes read
  2510 00005A2D FF0D[D4750000]      <1> 	dec	dword [u.count]
  2511                              <1> 		; dec u.count / decrement the number of bytes to be read
  2512                              <1> 		; bne 1f / any more bytes to read? ; yes, branch
  2513 00005A33 C3                  <1> 	retn
  2514                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2515                              <1> 		             ; / 'readi' by:
  2516                              <1> 		;/ (1) pop the return address off the stack into r0
  2517                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2518                              <1> 	;1:
  2519                              <1> 		; clr	*$ps / clear processor status
  2520                              <1> 		; rts r0 / return to address currently on top of stack
  2521                              <1> 
  2522                              <1> trans_addr_r:
  2523                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2524                              <1> 	;	-'add_to_swap_queue' call is disabled as temporary-
  2525                              <1> 	; Translate virtual address to physical address 
  2526                              <1> 	; for reading from user's memory space
  2527                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2528                              <1> 	; 18/10/2015
  2529                              <1> 	; 10/07/2015
  2530                              <1> 	; 09/06/2015
  2531                              <1> 	; 08/06/2015 
  2532                              <1> 	; 04/06/2015
  2533                              <1> 	;
  2534                              <1> 	; 18/10/2015
  2535 00005A34 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2536 00005A36 EB04                <1> 	jmp 	short trans_addr_rw
  2537                              <1> 
  2538                              <1> 	;push	eax
  2539                              <1> 	;push	ebx
  2540                              <1> 	;mov	ebx, [u.base]
  2541                              <1> 	;call	get_physical_addr ; get physical address
  2542                              <1> 	;;jnc	short cpass_0
  2543                              <1> 	;jnc	short passc_1
  2544                              <1> 	;mov	[u.error], eax
  2545                              <1> 	;;pop	ebx
  2546                              <1> 	;;pop	eax
  2547                              <1> 	;jmp	error
  2548                              <1> ;cpass_0:
  2549                              <1> 	; 18/10/2015
  2550                              <1> 	; 20/05/2015
  2551                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2552                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2553                              <1> 	;pop	ebx
  2554                              <1> 	;pop	eax
  2555                              <1> 	;retn	; 08/06/2015
  2556                              <1> 
  2557                              <1> trans_addr_w:
  2558                              <1> 	; 31/12/2021
  2559                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2560                              <1> 	;	-'add_to_swap_queue' call is disabled as temporary-
  2561                              <1> 	; Translate virtual address to physical address
  2562                              <1> 	; for writing to user's memory space
  2563                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2564                              <1> 	; 18/10/2015
  2565                              <1> 	; 29/07/2015
  2566                              <1> 	; 10/07/2015
  2567                              <1> 	; 09/06/2015
  2568                              <1> 	; 08/06/2015
  2569                              <1> 	; 04/06/2015 (passc)
  2570                              <1> 	;
  2571                              <1> 	; 18/10/2015
  2572 00005A38 29D2                <1> 	sub	edx, edx
  2573 00005A3A FEC2                <1> 	inc	dl ; 1 (write access sign)
  2574                              <1> trans_addr_rw:
  2575 00005A3C 50                  <1> 	push	eax
  2576 00005A3D 53                  <1> 	push	ebx
  2577                              <1> 	; 18/10/2015
  2578 00005A3E 52                  <1> 	push 	edx ; r/w sign (in DL)
  2579                              <1> 	;
  2580 00005A3F 8B1D[D0750000]      <1> 	mov	ebx, [u.base]
  2581 00005A45 E856D7FFFF          <1> 	call	get_physical_addr ; get physical address
  2582 00005A4A 730A                <1> 	jnc	short passc_0
  2583 00005A4C A3[20760000]        <1> 	mov	[u.error], eax
  2584                              <1> 	;pop	edx
  2585                              <1> 	;pop 	ebx
  2586                              <1> 	;pop	eax
  2587 00005A51 E9F2E0FFFF          <1> 	jmp	error
  2588                              <1> passc_0:
  2589 00005A56 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2590 00005A59 5A                  <1> 	pop	edx ; 18/10/2015
  2591 00005A5A 7517                <1> 	jnz	short passc_1
  2592                              <1> 	; 18/10/2015
  2593 00005A5C 20D2                <1> 	and 	dl, dl
  2594 00005A5E 7413                <1> 	jz	short passc_1
  2595                              <1> 	; 20/05/2015
  2596                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2597                              <1> 	; EBX = linear address
  2598 00005A60 51                  <1> 	push 	ecx
  2599                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2 (BugFix)
  2600 00005A61 53                  <1> 	push	ebx ;* ; BugFix  ; 31/12/2021
  2601 00005A62 E8A8D6FFFF          <1> 	call 	copy_page
  2602 00005A67 5B                  <1> 	pop	ebx ;* ; BugFix  ; 31/12/2021
  2603 00005A68 59                  <1> 	pop	ecx
  2604 00005A69 7217                <1> 	jc	short passc_2
  2605                              <1> 	; 30/11/2021
  2606                              <1> 	;push	eax ; physical address of the new/allocated page
  2607                              <1> 	;call	add_to_swap_queue
  2608                              <1> 	;pop	eax
  2609                              <1> 	; 18/10/2015
  2610 00005A6B 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2611                              <1> 	;mov 	ecx, PAGE_SIZE
  2612                              <1> 	;sub	ecx, ebx 
  2613 00005A71 01D8                <1> 	add	eax, ebx  
  2614                              <1> passc_1: 
  2615                              <1> 	; 18/10/2015
  2616                              <1> 	; 20/05/2015
  2617 00005A73 A3[14760000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2618 00005A78 66890D[18760000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2619 00005A7F 5B                  <1> 	pop	ebx
  2620 00005A80 58                  <1> 	pop	eax
  2621 00005A81 C3                  <1> 	retn	; 08/06/2015
  2622                              <1> passc_2:
  2623 00005A82 C705[20760000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2623 00005A8A 0000                <1>
  2624                              <1> 	;pop 	ebx
  2625                              <1> 	;pop	eax
  2626 00005A8C E9B7E0FFFF          <1> 	jmp	error
  2627                              <1> 
  2628                              <1> 	; 09/03/2022
  2629                              <1> 	; 25/12/2021
  2630                              <1> 	; 11/12/2021
  2631                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2632                              <1> writei:
  2633                              <1> 	; 20/05/2015
  2634                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2635                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2636                              <1> 	;
  2637                              <1> 	; Write data to file with inode number in R1
  2638                              <1> 	; 
  2639                              <1> 	; INPUTS ->
  2640                              <1> 	;    r1 - inode number
  2641                              <1> 	;    u.count - byte count to be written
  2642                              <1> 	;    u.base - points to user buffer
  2643                              <1> 	;    u.fofp - points to word with current file offset
  2644                              <1> 	; OUTPUTS ->
  2645                              <1> 	;    u.count - cleared
  2646                              <1> 	;    u.nread - accumulates total bytes passed back	
  2647                              <1> 	; ((AX = R1))
  2648                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2649                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2650                              <1> 
  2651 00005A91 31C9                <1> 	xor	ecx, ecx
  2652 00005A93 890D[D8750000]      <1> 	mov 	[u.nread], ecx  ; 0
  2653                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2654                              <1> 		            ; / read or write calls
  2655 00005A99 66890D[18760000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2656 00005AA0 390D[D4750000]      <1> 	cmp 	[u.count], ecx
  2657                              <1> 	;	; tst u.count / test the byte count specified by the user
  2658 00005AA6 7701                <1> 	ja 	short writei_1 ; 1f
  2659                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2660 00005AA8 C3                  <1> 	retn
  2661                              <1> 	;	; rts r0 / no, return - no writing to do
  2662                              <1> writei_1: ;1:
  2663                              <1> 	;	; mov r1 ,-(sp) / save the i-node number on the stack
  2664                              <1> 	;cmp 	ax, 40
  2665                              <1> 	;	; cmp r1,$40.
  2666                              <1> 	;	; / does the i-node number indicate a special file?
  2667                              <1>         ;ja	dskw 
  2668                              <1> 	;	; bgt dskw / no, branch to standard file output
  2669                              <1> 
  2670                              <1> 	; 28/11/2021
  2671 00005AA9 F605[1E760000]FF    <1> 	test	byte [u.kcall], 0FFh
  2672 00005AB0 750C                <1> 	jnz	short writei_2  ; 'writei' called by 'mkdir'
  2673                              <1> 
  2674                              <1> 	; eax = inode number
  2675                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2676 00005AB2 E85EFAFFFF          <1> 	call	iget
  2677                              <1> ;writei_2:
  2678                              <1> 	; 28/11/2021
  2679                              <1> 	; eax = inode number
  2680                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2681 00005AB7 E871020000          <1> 	call	is_regular_file
  2682                              <1> 	;jz	dskw ; regular file 
  2683                              <1> 	; 25/12/2021
  2684 00005ABC 7505                <1> 	jnz	short writei_5 ; device file
  2685                              <1> writei_2:	 ; 09/03/2022 
  2686                              <1> 	; regular file
  2687 00005ABE E9FD000000          <1> 	jmp	dskw
  2688                              <1> writei_5:
  2689                              <1> 	; (20/05/2015)
  2690 00005AC3 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2691                              <1> 	
  2692                              <1> 	; 28/11/2021	
  2693                              <1> 	; device file
  2694 00005AC4 BB[DE5A0000]        <1> 	mov	ebx, writei_4
  2695 00005AC9 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2696 00005ACC 720E                <1> 	jb	short writei_3
  2697 00005ACE 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2698 00005AD1 7709                <1> 	ja	short writei_3 ; 11/12/2021	
  2699                              <1> 	
  2700                              <1> 	; convert v2 inode number to v1 device inode number
  2701 00005AD3 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2702 00005AD5 89C1                <1> 	mov	ecx, eax
  2703 00005AD7 C0E102              <1> 	shl	cl, 2 ; * 4
  2704 00005ADA 01CB                <1> 	add	ebx, ecx
  2705                              <1> writei_3:
  2706 00005ADC FF23                <1> 	jmp	dword [ebx]	
  2707                              <1> 		; jmp *1f-2(r1)
  2708                              <1> 		; / jump table and jump to the appropriate routine
  2709                              <1> writei_4: ;1:
  2710 00005ADE [1E590000]          <1> 	dd	null ; 28/11/2021
  2711 00005AE2 [2E5B0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2712                              <1> 		 ;wtty / tty; r1=2
  2713                              <1> 		 ;wppt / ppt; r1=4
  2714 00005AE6 [905B0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2715                              <1> 		 ;wmem / mem; r1=6
  2716                              <1> 		 ;wrf0 / rf0
  2717                              <1> 		 ;wrk0 / rk0
  2718                              <1> 		 ;wtap / tap0
  2719                              <1> 		 ;wtap / tap1
  2720                              <1> 		 ;wtap / tap2
  2721                              <1> 		 ;wtap / tap3
  2722                              <1> 		 ;wtap / tap4
  2723                              <1> 		 ;wtap / tap5
  2724                              <1> 		 ;wtap / tap6
  2725                              <1> 		 ;wtap / tap7
  2726 00005AEA [4A610000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2727 00005AEE [4A610000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2728 00005AF2 [4A610000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2729 00005AF6 [4A610000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2730 00005AFA [4A610000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2731 00005AFE [4A610000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2732 00005B02 [815B0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2733 00005B06 [7B5B0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2734                              <1> 		 ;xmtt / tty0
  2735 00005B0A [7B5B0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2736                              <1> 		 ;xmtt / tty1
  2737 00005B0E [7B5B0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2738                              <1> 		 ;xmtt / tty2
  2739 00005B12 [7B5B0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2740                              <1> 		 ;xmtt / tty3
  2741 00005B16 [7B5B0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2742                              <1> 		 ;xmtt / tty4
  2743 00005B1A [7B5B0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2744                              <1> 		 ;xmtt / tty5
  2745 00005B1E [7B5B0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2746                              <1> 		 ;xmtt / tty6
  2747 00005B22 [7B5B0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2748                              <1> 		 ;xmtt / tty7
  2749 00005B26 [7B5B0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2750                              <1> 		; / wlpr / lpr
  2751 00005B2A [7B5B0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)
  2752                              <1> 
  2753                              <1> ;	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2754                              <1> ;null:
  2755                              <1> ;	xor	eax, eax
  2756                              <1> ;	pop	eax
  2757                              <1> ;	retn	
  2758                              <1> 
  2759                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2760                              <1> wtty: ; write to console tty (write to screen)
  2761                              <1> 	; 18/11/2015
  2762                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2763                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2764                              <1> 	;
  2765                              <1> 	; Console tty output is on current video page
  2766                              <1> 	; Console tty character output procedure is changed here
  2767                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2768                              <1> 	;
  2769 00005B2E 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2770 00005B35 8AA3[D7710000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2771 00005B3B 88E0                <1> 	mov	al, ah ; 07/07/2014
  2772                              <1> wttys:	
  2773                              <1> 	; 10/10/2013
  2774 00005B3D 8825[E1750000]      <1> 	mov 	[u.ttyn], ah
  2775                              <1> 	; 13/01/2014
  2776 00005B43 FEC0                <1> 	inc	al
  2777 00005B45 A2[E3750000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2778                              <1> wtty_nc: ; 15/05/2013
  2779                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2780 00005B4A E8FD000000          <1> 	call	cpass
  2781                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2782                              <1> 		             ; / none go to return address in syswrite
  2783                              <1> 		; tst r1 / is character = null
  2784                              <1> 		; beq wtty / yes, get next character
  2785                              <1> 	; 10/10/2013
  2786 00005B4F 7428                <1> 	jz	short wret
  2787                              <1> 	;1 :
  2788                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2789                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2790                              <1> 		;	          / than 20
  2791                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2792                              <1> 	; 27/06/2014
  2793                              <1> wtty_1:
  2794                              <1> 	; AH = tty number
  2795                              <1> 	; AL = ASCII code of the character
  2796                              <1> 	; 15/04/2014
  2797                              <1> 	;push	ax
  2798                              <1> 	; 11/12/2021
  2799 00005B51 50                  <1> 	push	eax
  2800 00005B52 E82F0A0000          <1> 	call	putc ; 14/05/2013
  2801 00005B57 731D                <1> 	jnc	short wtty_2
  2802                              <1> 	; 18/11/2015
  2803 00005B59 E834F5FFFF          <1> 	call	idle
  2804                              <1> 	;mov	ax, [esp]
  2805                              <1> 	; 11/12/2021
  2806 00005B5E 8B0424              <1> 	mov	eax, [esp]
  2807 00005B61 E8200A0000          <1> 	call	putc
  2808 00005B66 730E                <1> 	jnc	short wtty_2 
  2809                              <1> 	; 02/06/2014
  2810 00005B68 8A25[E1750000]      <1> 	mov	ah, [u.ttyn]
  2811 00005B6E E8ACF5FFFF          <1> 	call	sleep
  2812                              <1> 	;pop	ax
  2813                              <1> 	; 11/12/2021
  2814 00005B73 58                  <1> 	pop	eax
  2815 00005B74 EBDB                <1> 	jmp 	short wtty_1
  2816                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2817                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2818                              <1> 			      ; / console tty and
  2819                              <1> 		; br 	2f / place character in list; if none available
  2820                              <1> 		   	  ; / branch to put process to sleep
  2821                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2822                              <1> wtty_2:
  2823                              <1> 	; 15/04/2014
  2824                              <1> 	;pop	ax
  2825                              <1> 	; 11/12/2021
  2826 00005B76 58                  <1> 	pop	eax
  2827 00005B77 EBD1                <1> 	jmp	short wtty_nc
  2828                              <1> 		; br wtty
  2829                              <1> wret:	; 10/10/2013 (20/05/2015)
  2830 00005B79 58                  <1> 	pop	eax
  2831 00005B7A C3                  <1> 	retn
  2832                              <1> 	;2:
  2833                              <1> 		;mov	r1,-(sp) / place character on stack
  2834                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2835                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2836                              <1> 		;br	1b / try again to place character in clist and output
  2837                              <1> 
  2838                              <1> xmtt:   ; < send/write character to tty >
  2839                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2840                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2841                              <1> 	;
  2842                              <1> 	; Retro UNIX 8086 v1 modification !
  2843                              <1> 	; 
  2844                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2845                              <1> 	;		(exactly different than this one)
  2846                              <1> 	;	was in 'u9.s' file.
  2847                              <1> 	;
  2848 00005B7B 2C0A                <1> 	sub 	al, 10
  2849                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2850                              <1> 	; 10/10/2013
  2851 00005B7D 88C4                <1> 	mov	ah, al
  2852                              <1> 	; 28/07/2013
  2853 00005B7F EBBC                <1> 	jmp	short wttys
  2854                              <1> 
  2855                              <1> ;wppt:
  2856                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2857                              <1> ;		         / if none return to writei's calling routine
  2858                              <1> ;	jsr	r0,pptoc / output character on ppt
  2859                              <1> ;	br	wppt
  2860                              <1> wlpr:
  2861 00005B81 C705[20760000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2861 00005B89 0000                <1>
  2862 00005B8B E9B8DFFFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2863                              <1> 		;/	jsr	r0,cpass
  2864                              <1> 		;/	cmp	r0,$'a
  2865                              <1> 		;/	blo	1f
  2866                              <1> 		;/	cmp	r1,$'z
  2867                              <1> 		;/	bhi	1f
  2868                              <1> 		;/	sub	$40,r1
  2869                              <1> 		;/1:
  2870                              <1> 		;/	jsr	r0,lptoc
  2871                              <1> 		;/	br	wlpr
  2872                              <1> 		; br rmem / continue
  2873                              <1> 
  2874                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2875                              <1> 	; 17/10/2015
  2876                              <1> 	; 11/06/2015
  2877                              <1> 	; 24/05/2015
  2878                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2879                              <1> 	;
  2880 00005B90 813D[0F070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2880 00005B96 [B5500000]          <1>
  2881 00005B9A 7415                <1>         je      short wmem_acc_err
  2882                              <1> 	;
  2883 00005B9C 8B35[C0750000]      <1>         mov     esi, [u.fofp] 
  2884                              <1> wmem_1:
  2885 00005BA2 E8A5000000          <1> 	call	cpass
  2886                              <1> 		; jsr r0,cpass / get next character from users area of
  2887                              <1> 			     ; / core and put it in r1
  2888                              <1>         	; mov r1,-(sp) / put character on the stack
  2889                              <1> 	; 20/09/2013
  2890 00005BA7 74D0                <1> 	jz	short wret ; wmem_2  
  2891 00005BA9 8B1E                <1>         mov     ebx, [esi]
  2892                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2893 00005BAB FF06                <1>         inc     dword [esi] ; 17/10/2015
  2894                              <1> 		; inc *u.fofp / increment file offset to point to next
  2895                              <1> 			    ; / available location in file
  2896 00005BAD 8803                <1> 	mov	[ebx], al	
  2897                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2898                              <1> 			        ; / assigned to it
  2899 00005BAF EBF1                <1> 	jmp	short wmem_1
  2900                              <1> 		; br wmem / continue
  2901                              <1> 	;1:
  2902                              <1> 	;jmp	error / ?
  2903                              <1> ;wmem_2:	
  2904                              <1> ;	; 20/09/2013
  2905                              <1> ;	pop	ax
  2906                              <1> ;	retn
  2907                              <1> 
  2908                              <1> wmem_acc_err:
  2909 00005BB1 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2909 00005BB9 0000                <1>
  2910 00005BBB E988DFFFFF          <1> 	jmp	error
  2911                              <1> 
  2912                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2913                              <1> 
  2914                              <1> dskw: ; / write routine for non-special files
  2915                              <1> 	;
  2916                              <1> 	; 28/11/2021
  2917                              <1> 	; 25/07/2015
  2918                              <1> 	; 16/06/2015
  2919                              <1> 	; 09/06/2015
  2920                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2921                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2922                              <1> 
  2923                              <1> 	; 01/08/2013 (mkdir_w check)
  2924                              <1> 	;push	ax ; 26/04/2013
  2925                              <1> 	;	; mov (sp),r1 / get an i-node number from the stack into r1
  2926                              <1> 	; 28/11/2021
  2927 00005BC0 50                  <1> 	push	eax
  2928                              <1> 	; AX = inode number
  2929 00005BC1 E84FF9FFFF          <1> 	call	iget
  2930                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2931                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2932 00005BC6 8B1D[C0750000]      <1>         mov     ebx, [u.fofp] 
  2933 00005BCC 8B13                <1> 	mov 	edx, [ebx]
  2934                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2935                              <1> 			       ; / in the fsp entry for this file] in r2
  2936 00005BCE 0315[D4750000]      <1> 	add 	edx, [u.count]	
  2937                              <1> 		; add u.count,r2 / no. of bytes to be written
  2938                              <1> 			       ; / + file offset is put in r2
  2939                              <1> 	;; 16/06/2015        
  2940                              <1> 	;cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2941                              <1> 	;jna	short dskw_0
  2942                              <1> 	;mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2943                              <1> 	;jmp	error
  2944                              <1> dskw_0:	
  2945                              <1> 	; 28/11/2021
  2946 00005BD4 3B15[60710000]      <1> 	cmp	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2947                              <1> 	;cmp	dx, [i.size]
  2948                              <1> 	;	; cmp r2,i.size / is this greater than the present size of
  2949                              <1> 		              ; / the file?
  2950 00005BDA 760B                <1> 	jna	short dskw_1
  2951                              <1> 		; blos 1f / no, branch
  2952 00005BDC 8915[60710000]      <1> 	mov	[i.size], edx ; 32 bit file size (runix v2 inode)
  2953                              <1> 	;mov	[i.size], dx
  2954                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2955                              <1> 			      ; / file offset + no. of data bytes
  2956 00005BE2 E8BFFAFFFF          <1> 	call	setimod
  2957                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2958                              <1> 		          ; / modified), stuff time of modification into
  2959                              <1> 	          	  ; / core image of i-node
  2960                              <1> dskw_1: ; 1:
  2961                              <1> 	; 28/11/2021
  2962                              <1> 	;call	mget
  2963 00005BE7 E8ABF5FFFF          <1> 	call	mget_w
  2964                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2965                              <1> 			    ; /	the next data byte
  2966                              <1> 	; eax = physical block/sector number
  2967 00005BEC 8B1D[C0750000]      <1> 	mov     ebx, [u.fofp]
  2968 00005BF2 8B13                <1> 	mov	edx, [ebx]
  2969 00005BF4 81E2FF010000        <1> 	and	edx, 1FFh  
  2970                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2971 00005BFA 750C                <1> 	jnz	short dskw_2
  2972                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2973                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2974 00005BFC 813D[D4750000]0002- <1> 	cmp	dword [u.count], 512
  2974 00005C04 0000                <1>
  2975                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2976                              <1> 				  ; / an entire block? (i.e., no. of
  2977 00005C06 7305                <1> 	jnb	short dskw_3
  2978                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2979                              <1> 			; / Yes, branch. Don't have to read block
  2980                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2981                              <1>    		; / overwritten).
  2982 00005C08 E803060000          <1> 	call	dskrd
  2983                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2984                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2985                              <1> dskw_3: ; 3:
  2986                              <1> 	; EAX (r1) = block/sector number
  2987 00005C0D E870060000          <1> 	call	wslot
  2988                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2989                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2990 00005C12 803D[1E760000]00    <1> 	cmp	byte [u.kcall], 0
  2991 00005C19 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2992                              <1> 	;
  2993 00005C1B 66833D[18760000]00  <1> 	cmp	word [u.pcount], 0
  2994 00005C23 7705                <1> 	ja	short dskw_5
  2995                              <1> dskw_4:
  2996                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2997 00005C25 E80AFEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2998                              <1> dskw_5:
  2999                              <1> 	; eBX (r5) = system (I/O) buffer address
  3000 00005C2A E87D000000          <1> 	call	sioreg
  3001                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3002                              <1> 			     ; / r1 = address of data, r2 points to location
  3003                              <1> 			     ; / in buffer in which to start writing data
  3004                              <1> 	; eSI = file (user data) offset
  3005                              <1> 	; eDI = sector (I/O) buffer offset
  3006                              <1> 	; eCX = byte count
  3007                              <1> 	;
  3008 00005C2F F3A4                <1>   	rep	movsb
  3009                              <1> 		; movb (r1 )+,(r2)+ 
  3010                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3011                              <1> 		; dec r3 / decrement no. of bytes to be written
  3012                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3013                              <1> 	; 25/07/2015
  3014                              <1> 	; eax = remain bytes in buffer
  3015                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3016 00005C31 09C0                <1> 	or	eax, eax
  3017 00005C33 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  3018                              <1> dskw_6:
  3019 00005C35 E864060000          <1> 	call	dskwr
  3020                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3021 00005C3A 833D[D4750000]00    <1>         cmp     dword [u.count], 0
  3022                              <1> 		; tst u.count / any more data to write?
  3023 00005C41 77A4                <1> 	ja	short dskw_1
  3024                              <1> 		; bne 1b / yes, branch
  3025                              <1> 	; 03/08/2013
  3026 00005C43 C605[1E760000]00    <1> 	mov	byte [u.kcall], 0
  3027                              <1> 	; 20/09/2013 (;;)
  3028                              <1> 	;pop	ax
  3029                              <1> 	; 28/11/2021
  3030 00005C4A 58                  <1> 	pop	eax  
  3031 00005C4B C3                  <1> 	retn
  3032                              <1> 	;;jmp 	short dskw_ret 
  3033                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3034                              <1> 
  3035                              <1> 	; 24/12/2021
  3036                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3037                              <1> cpass: ; / get next character from user area of core and put it in r1
  3038                              <1> 	; 18/10/2015
  3039                              <1> 	; 10/10/2015
  3040                              <1> 	; 10/07/2015
  3041                              <1> 	; 02/07/2015
  3042                              <1> 	; 01/07/2015
  3043                              <1> 	; 24/06/2015
  3044                              <1> 	; 08/06/2015
  3045                              <1> 	; 04/06/2015
  3046                              <1> 	; 20/05/2015
  3047                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3048                              <1> 	;
  3049                              <1> 	; INPUTS -> 
  3050                              <1> 	;     [u.base] = virtual address in user area
  3051                              <1> 	;     [u.count] = byte count (max.)
  3052                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3053                              <1> 	; OUTPUTS -> 
  3054                              <1> 	;     AL = the character which is pointed by [u.base]
  3055                              <1> 	;     zf = 1 -> transfer count has been completed	
  3056                              <1>         ;
  3057                              <1> 	; ((Modified registers: EAX, EDX, ECX))
  3058                              <1> 	;
  3059                              <1> 	;
  3060 00005C4C 833D[D4750000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3061                              <1> 		; tst u.count / have all the characters been transferred
  3062                              <1> 			    ; / (i.e., u.count, # of chars. left
  3063 00005C53 763F                <1> 	jna	short cpass_3
  3064                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3065 00005C55 FF0D[D4750000]      <1> 	dec	dword [u.count]
  3066                              <1> 		; dec u.count / no, decrement u.count
  3067                              <1>         ; 19/05/2015 
  3068                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3069                              <1> 	;		      to physical address
  3070 00005C5B 66833D[18760000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3071                              <1> 			     ; 1-4095 --> use previous physical base address
  3072                              <1> 			     ; in [u.pbase]
  3073 00005C63 770E                <1> 	ja	short cpass_1
  3074                              <1> 	; 02/07/2015
  3075 00005C65 833D[10760000]00    <1> 	cmp	dword [u.ppgdir], 0  ; is the caller os kernel
  3076 00005C6C 7427                <1> 	je	short cpass_k 	; (sysexec, '/etc/init') ? 
  3077                              <1> 	; 08/06/2015 - 10/07/2015
  3078 00005C6E E8C1FDFFFF          <1> 	call	trans_addr_r
  3079                              <1> cpass_1:
  3080                              <1> 	; 02/07/2015
  3081                              <1> 	; 24/06/2015
  3082 00005C73 66FF0D[18760000]    <1> 	dec	word [u.pcount]
  3083                              <1> cpass_2: 
  3084                              <1> 	; 10/10/2015
  3085                              <1> 	; 02/07/2015
  3086 00005C7A 8B15[14760000]      <1> 	mov	edx, [u.pbase]
  3087 00005C80 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3088                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3089                              <1> 				; / by u.base and put it in r1
  3090 00005C82 FF05[D8750000]      <1> 	inc	dword [u.nread]
  3091                              <1> 		; inc u.nread / increment no. of bytes transferred
  3092 00005C88 FF05[D0750000]      <1> 	inc	dword [u.base]
  3093                              <1> 		; inc u.base / increment the buffer address to point to the
  3094                              <1> 			   ; / next byte
  3095 00005C8E FF05[14760000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3096                              <1> cpass_3:
  3097 00005C94 C3                  <1> 	retn
  3098                              <1> 		; rts	r0 / next byte
  3099                              <1> 	; 1: 
  3100                              <1> 		; mov (sp)+,r0 
  3101                              <1> 		         ; / put return address of calling routine into r0
  3102                              <1> 		; mov (sp)+,r1 / i-number in r1
  3103                              <1> 		; rts r0 / non-local return
  3104                              <1> cpass_k:
  3105                              <1> 	; 02/07/2015
  3106                              <1> 	; The caller is os kernel 
  3107                              <1> 	; (get sysexec arguments from kernel's memory space)
  3108                              <1> 	;
  3109 00005C95 8B1D[D0750000]      <1> 	mov	ebx, [u.base]
  3110 00005C9B 66C705[18760000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3110 00005CA3 10                  <1>
  3111 00005CA4 891D[14760000]      <1> 	mov	[u.pbase], ebx
  3112 00005CAA EBCE                <1> 	jmp	short cpass_2
  3113                              <1> 	
  3114                              <1> sioreg: 
  3115                              <1> 	; 25/07/2015
  3116                              <1> 	; 18/07/2015
  3117                              <1> 	; 02/07/2015
  3118                              <1> 	; 17/06/2015
  3119                              <1> 	; 09/06/2015
  3120                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3121                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3122                              <1> 	;
  3123                              <1> 	; INPUTS -> 
  3124                              <1> 	;     eBX = system buffer (data) address (r5)
  3125                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3126                              <1> 	;     [u.base] = virtual address of the user buffer
  3127                              <1> 	;     [u.pbase] = physical address of the user buffer
  3128                              <1> 	;     [u.count] = byte count
  3129                              <1> 	;     [u.pcount] = byte count within page frame 			
  3130                              <1> 	; OUTPUTS -> 
  3131                              <1> 	;     eSI = user data offset (r1)
  3132                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3133                              <1> 	;     eCX = byte count (r3)
  3134                              <1> 	;     EAX = remain bytes after byte count within page frame
  3135                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3136                              <1>         ;
  3137                              <1> 	; ((Modified registers:  EDX))
  3138                              <1>  
  3139 00005CAC 8B35[C0750000]      <1>         mov     esi, [u.fofp]
  3140 00005CB2 8B3E                <1>         mov     edi, [esi]
  3141                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3142 00005CB4 89F9                <1> 	mov	ecx, edi
  3143                              <1> 		; mov r2,r3 / and also to r3
  3144 00005CB6 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3145                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3146 00005CBC 81E7FF010000        <1> 	and	edi, 1FFh
  3147                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3148 00005CC2 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3149                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3150                              <1> 			  ; / where data is to be placed
  3151                              <1>                 ; mov u.base,r1 / address of data is in r1
  3152 00005CC4 F7D9                <1> 	neg	ecx
  3153                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3154                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3155 00005CC6 3B0D[D4750000]      <1> 	cmp	ecx, [u.count]
  3156                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3157                              <1> 			       ; / to be written to the file
  3158 00005CCC 7606                <1> 	jna	short sioreg_0
  3159                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3160                              <1> 			 ; / in the file block as the number to be written
  3161 00005CCE 8B0D[D4750000]      <1> 	mov	ecx, [u.count]
  3162                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3163                              <1> 			       ; / bytes as the number to be written
  3164                              <1> sioreg_0:
  3165                              <1> 	; 17/06/2015
  3166 00005CD4 803D[1E760000]00    <1> 	cmp	byte [u.kcall], 0 
  3167 00005CDB 7613                <1> 	jna	short sioreg_1
  3168                              <1> 	; 25/07/2015
  3169                              <1> 	 ; the caller is 'mkdir' or 'namei'
  3170 00005CDD A1[D0750000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3171 00005CE2 A3[14760000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3172 00005CE7 66890D[18760000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3173 00005CEE EB0B                <1> 	jmp	short sioreg_2
  3174                              <1> sioreg_1:
  3175                              <1> 	; 25/07/2015
  3176                              <1> 	; 18/07/2015
  3177                              <1> 	; 09/06/2015 
  3178 00005CF0 0FB715[18760000]    <1> 	movzx	edx, word [u.pcount]
  3179                              <1> 		; ecx and [u.pcount] are always > 0, here
  3180 00005CF7 39D1                <1> 	cmp	ecx, edx	
  3181 00005CF9 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3182                              <1> sioreg_2: ; 2:
  3183 00005CFB 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3184                              <1> sioreg_3:
  3185 00005CFD 010D[D8750000]      <1> 	add 	[u.nread], ecx
  3186                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3187                              <1> 			         ; / during write is put into u.nread
  3188 00005D03 290D[D4750000]      <1> 	sub 	[u.count], ecx
  3189                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3190                              <1> 			       ; / must be written or read
  3191 00005D09 010D[D0750000]      <1> 	add 	[u.base], ecx
  3192                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3193                              <1> 			      ; / data bytes
  3194 00005D0F 010E                <1>         add 	[esi], ecx 
  3195                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3196                              <1> 			       ; / + old file offset
  3197                              <1> 	; 25/07/2015
  3198 00005D11 8B35[14760000]      <1> 	mov	esi, [u.pbase]
  3199 00005D17 66290D[18760000]    <1> 	sub	[u.pcount], cx
  3200 00005D1E 010D[14760000]      <1> 	add	[u.pbase], ecx
  3201 00005D24 C3                  <1>         retn
  3202                              <1> 		; rts r0
  3203                              <1> 		; transfer count > [u.pcount]
  3204                              <1> sioreg_4:
  3205                              <1> 	; 25/07/2015
  3206                              <1> 	; transfer count > [u.pcount] 
  3207                              <1> 	; (ecx > edx)
  3208 00005D25 89C8                <1> 	mov	eax, ecx
  3209 00005D27 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3210 00005D29 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3211 00005D2B EBD0                <1> 	jmp	short sioreg_3
  3212                              <1> 
  3213                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  3214                              <1> is_regular_file:
  3215                              <1> 	; check if it is a regular file or device file inode
  3216                              <1> 	;
  3217                              <1> 	; INPUT:
  3218                              <1> 	;	current inode
  3219                              <1> 	; OUTPUT:
  3220                              <1> 	;	cf = 0 and zf = 1 -> regular file
  3221                              <1> 	;	cf = 0 and zf = 0 -> device file
  3222                              <1> 	;	cf = 1 -> invalid file (jump to 'error')
  3223                              <1> 	;
  3224                              <1> 	; Modified registers: ecx (cl)
  3225                              <1> 
  3226                              <1> 	; 28/11/2021
  3227 00005D2D 8A0D[59710000]      <1> 	mov	cl, [i.flgs+1]
  3228 00005D33 F6C180              <1> 	test	cl, 80h		; regular file ?
  3229 00005D36 7514                <1> 	jnz	short isregf_1  ; yes 
  3230 00005D38 80E120              <1> 	and	cl, 20h 	; device file ?
  3231 00005D3B 7511                <1> 	jnz	short isregf_2  ; yes 
  3232                              <1> 
  3233                              <1> 	; 28/11/2021
  3234                              <1> 	; invalid inode/file type !
  3235 00005D3D C705[20760000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  3235 00005D45 0000                <1>
  3236                              <1> 	;stc
  3237                              <1> 	;retn
  3238 00005D47 E9FCDDFFFF          <1> 	jmp	error
  3239                              <1> isregf_1:
  3240 00005D4C 30C9                <1> 	xor	cl, cl  ; cl = 0
  3241                              <1> 	; zf = 1
  3242                              <1> 	;retn
  3243                              <1> isregf_2:
  3244                              <1> 	; zf = 0
  3245                              <1> 	; cl = 20h
  3246 00005D4E C3                  <1> 	retn	
  2093                                  %include 'u7.s'      ; 18/04/2015
  2094                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2095                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2096                              <1> ; ****************************************************************************
  2097                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC
  2098                              <1> ; Last Modification: 03/03/2022
  2099                              <1> ; ----------------------------------------------------------------------------
  2100                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2101                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2102                              <1> ;
  2103                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2104                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2105                              <1> ; <Bell Laboratories (17/3/1972)>
  2106                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2107                              <1> ;
  2108                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2109                              <1> ;
  2110                              <1> ; ****************************************************************************
  2111                              <1> 
  2112                              <1> sysmount: ; / mount file system; args special; name
  2113                              <1> 	; 08/02/2022
  2114                              <1> 	; 07/02/2022
  2115                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2116                              <1> 	; 14/11/2015
  2117                              <1> 	; 24/10/2015
  2118                              <1> 	; 13/10/2015
  2119                              <1> 	; 10/07/2015
  2120                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2121                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2122                              <1> 	;
  2123                              <1> 	; 'sysmount' anounces to the system that a removable 
  2124                              <1> 	; file system has been mounted on a special file.
  2125                              <1> 	; The device number of the special file is obtained via
  2126                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2127                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2128                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2129                              <1> 	; to read file system into core, i.e. the first block on the
  2130                              <1> 	; mountable file system is read in. This block is super block
  2131                              <1> 	; for the file system. This call is super user restricted.	
  2132                              <1> 	;
  2133                              <1> 	; Calling sequence:
  2134                              <1> 	;	sysmount; special; name
  2135                              <1> 	; Arguments:
  2136                              <1> 	;	special - pointer to name of special file (device)
  2137                              <1> 	;	name -  pointer to name of the root directory of the
  2138                              <1> 	;		newly mounted file system. 'name' should 
  2139                              <1> 	;		always be a directory.
  2140                              <1> 	; Inputs: - 
  2141                              <1> 	; Outputs: -
  2142                              <1> 	; ...............................................................
  2143                              <1> 	;				
  2144                              <1> 	; Retro UNIX 8086 v1 modification: 
  2145                              <1> 	;       'sysmount' system call has two arguments; so,
  2146                              <1> 	;	* 1st argument, special is pointed to by BX register
  2147                              <1> 	;	* 2nd argument, name is in CX register
  2148                              <1> 	;
  2149                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2150                              <1> 	;	       already modified for IBM PC compatibility and 
  2151                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2152                              <1> 	
  2153                              <1> 	;call	arg2
  2154                              <1> 		; jsr r0,arg2 / get arguments special and name
  2155 00005D4F 891D[C8750000]      <1> 	mov	[u.namep], ebx
  2156                              <1> 	; 07/02/2022
  2157                              <1> 	;push	ecx ; directory name
  2158                              <1> 	;cmp	dword [mnti], 0 ; 11/01/2022 (32 bit inode number)
  2159 00005D55 66833D[98750000]00  <1> 	cmp	word [mnti], 0
  2160                              <1> 		; tst mnti / is the i-number of the cross device file
  2161                              <1> 			 ; / zero?
  2162                              <1> 	;;ja	error
  2163                              <1>         	; bne errora / no, error
  2164                              <1> 	;ja	sysmnt_err0
  2165                              <1> 	; 11/01/2022
  2166 00005D5D 7605                <1> 	jna	short sysmnt_0 ; 12/01/2022
  2167 00005D5F E901010000          <1> 	jmp	sysmnt_err0
  2168                              <1> sysmnt_0:
  2169                              <1> 	; 07/02/2022
  2170 00005D64 51                  <1> 	push	ecx ; directory name
  2171 00005D65 E8E3000000          <1> 	call	getspl
  2172                              <1> 		; jsr r0,getspl / get special files device number in r1
  2173                              <1> 	; 07/02/2022
  2174 00005D6A 8F05[C8750000]      <1> 	pop	dword [u.namep] ; directory name
  2175                              <1> 	; 13/10/2015
  2176                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2177                              <1>         ; 11/01/2022
  2178 00005D70 29DB                <1> 	sub	ebx, ebx
  2179 00005D72 88C3                <1> 	mov	bl, al
  2180 00005D74 F683[DA6B0000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2181 00005D7B 750F                <1> 	jnz	short sysmnt_1
  2182                              <1> sysmnt_err1:
  2183 00005D7D C705[20760000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2183 00005D85 0000                <1>
  2184 00005D87 E9BCDDFFFF          <1> 	jmp	error
  2185                              <1> sysmnt_1:
  2186                              <1> 	; 07/02/2022
  2187                              <1> 	;pop	dword [u.namep]
  2188                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2189                              <1> 				  ; / on the device
  2190                              <1> 	; 14/11/2015
  2191 00005D8C 53                  <1> 	push	ebx ; 13/10/2015
  2192                              <1> 		; mov r1,-(sp) / save the device number
  2193                              <1>         ;
  2194 00005D8D E8C6ECFFFF          <1> 	call	namei
  2195                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2196                              <1> 		       ; ax = 0 -> file not found 	
  2197                              <1> 	;jz	error
  2198                              <1> 	;jc	error
  2199                              <1> 		; jsr r0,namei / get the i-number of the file
  2200                              <1>                	; br errora
  2201 00005D92 730F                <1> 	jnc	short sysmnt_2
  2202                              <1> sysmnt_err2:
  2203 00005D94 C705[20760000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2203 00005D9C 0000                <1>
  2204 00005D9E E9A5DDFFFF          <1> 	jmp	error
  2205                              <1> sysmnt_2:
  2206                              <1> 	; 11/01/2022
  2207 00005DA3 A3[98750000]        <1> 	mov	[mnti], eax ; 32 bit inode number (<= 65535)	
  2208                              <1> 	;mov	[mnti], ax
  2209                              <1>         	; mov r1,mnti / put it in mnti
  2210                              <1> 	; 11/01/2022
  2211 00005DA8 BB[58780000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2212                              <1> sysmnt_3: ;1:
  2213                              <1>         ;cmp	byte [ebx+1], 0
  2214                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2215                              <1> 			   ; / dismountable device set?
  2216                              <1>         ;jna	short sysmnt_4		
  2217                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2218                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2219                              <1> 	;jmp	short sysmnt_3
  2220                              <1> sysmnt_4:   
  2221 00005DAD 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2222 00005DAE A2[8F750000]        <1> 	mov	[mdev], al
  2223                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2224 00005DB3 8803                <1> 	mov	[ebx], al
  2225                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2226                              <1> 			      ; / of the I/O queue entry
  2227                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2228                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2229 00005DB5 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2230                              <1> 		; bis $2000,sb1 / set the read bit
  2231                              <1> 	; Retro UNIX 386 v1 modification : 
  2232                              <1> 	;	32 bit block number at buffer header offset 4
  2233 00005DBA C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2234 00005DC1 E82B060000          <1> 	call 	diskio
  2235 00005DC6 7345                <1> 	jnc	short sysmnt_5
  2236 00005DC8 31C0                <1> 	xor 	eax, eax
  2237 00005DCA 66A3[98750000]      <1> 	mov	[mnti], ax ; 0
  2238 00005DD0 A2[8F750000]        <1> 	mov	[mdev], al ; 0
  2239                              <1> 	;mov	[cdev], al ; 0
  2240                              <1> 	; 08/02/2022
  2241 00005DD5 803D[1F760000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2242 00005DDC 7508                <1> 	jne	short sysmnt_err3
  2243                              <1> 	; yes, clear [u.brwdev] for next check
  2244                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2245 00005DDE FE05[1F760000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2246 00005DE4 EB0A                <1> 	jmp	short sysmnt_err4
  2247                              <1> sysmnt_err3:	; 08/02/2022
  2248                              <1> 	; no, set [u.error] to disk read error
  2249 00005DE6 C705[20760000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2249 00005DEE 0000                <1>
  2250                              <1> sysmnt_err4:
  2251                              <1> 	; 08/02/2022
  2252                              <1> 	; 14/11/2015
  2253 00005DF0 FEC8                <1> 	dec 	al
  2254 00005DF2 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2255 00005DF4 FEC0                <1> 	inc	al
  2256 00005DF6 48                  <1> 	dec	eax
  2257 00005DF7 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2258 00005DFA E949DDFFFF          <1> 	jmp	error
  2259                              <1> sysmnt_invd:
  2260                              <1> 	; 08/02/2022
  2261 00005DFF C705[20760000]1C00- <1> 	mov	dword [u.error], ERR_INV_FS ; 28
  2261 00005E07 0000                <1>
  2262                              <1> 				 ;'invalid fs/superblock !' error
  2263 00005E09 30C0                <1> 	xor	al, al ; 0
  2264 00005E0B EBE3                <1> 	jmp	short sysmnt_err4
  2265                              <1> 
  2266                              <1> sysmnt_5:
  2267                              <1> 	; 08/02/2022
  2268                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1 BugFix)
  2269                              <1> 	;  v1.2 Note: This code will be changed for hard disk partitions
  2270                              <1> 	;	    ! (for now, rufs v2 floppy disks can be mounted) !		
  2271                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2272                              <1> 	; (Following check is needed to prevent mounting an
  2273                              <1> 	; invalid file system (invalid super block).
  2274                              <1> 	; 
  2275 00005E0D 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2276 00005E10 C0E002              <1> 	shl	al, 2 ; 4*index
  2277 00005E13 8B88[BE6B0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2278                              <1> 	;shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2279                              <1> 	; ecx = number of free map bytes (required)
  2280                              <1> 	;;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2281                              <1> 	;movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2282                              <1> 	; edx = number of free blocks map bytes
  2283                              <1> 	;;shl	edx, 3 ; convert free map bytes to free map bits
  2284                              <1> 	;cmp	ecx, edx ; compare free map bits and volume size
  2285                              <1> 	;		 ; (in sectors), if they are not equal
  2286                              <1> 	;		 ; the disk to be mounted is an...
  2287                              <1> 	;jne	short sysmnt_invd ; invalid disk !
  2288                              <1> 	;		 ; (which has not got a valid super bloc	
  2289                              <1> 	; 07/02/2022
  2290                              <1> 	;xor	al, al ; 08/02/2022
  2291                              <1> 	; 11/01/2022
  2292                              <1> 	; Retro UNIX 386 v2 superblock (offset 8, volume size)
  2293 00005E19 8B5310              <1> 	mov	edx, [ebx+16] ; SB.VolumeSize (in sectors)
  2294 00005E1C 39D1                <1> 	cmp	ecx, edx ; compare SB.VolumeSize and Disk volume size
  2295                              <1> 			 ; (in sectors), if they are not equal
  2296                              <1> 			 ; the disk to be mounted is an...	
  2297 00005E1E 75DF                <1> 	jne	short sysmnt_invd ; invalid disk !
  2298                              <1> 			 ; (which has not got a valid shuper block)
  2299                              <1> 	;
  2300 00005E20 C6430100            <1> 	mov	byte [ebx+1], 0
  2301                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2302                              <1> ;sysmnt_6: ;1:
  2303                              <1> 	;;cmp	byte [sb1+1], 0
  2304                              <1> 		; tstb sb1+1 / done reading?
  2305                              <1>    	;;jna	sysret
  2306                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2307                              <1> 	;;jmp	short sysmnt_6
  2308                              <1> 		;bne 1b / no, wait
  2309                              <1>         	;br sysreta / yes
  2310 00005E24 E93FDDFFFF          <1> 	jmp	sysret
  2311                              <1> 
  2312                              <1> sysumount: ; / special dismount file system
  2313                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2314                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2315                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2316                              <1> 	;
  2317                              <1> 	; 04/11/2013
  2318                              <1> 	; 09/07/2013
  2319                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2320                              <1> 	; indicated as an argument is no longer contain a removable
  2321                              <1> 	; file system. 'getspl' gets the device number of the special
  2322                              <1> 	; file. If no file system was mounted on that device an error
  2323                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2324                              <1> 	; to 'sysret'.
  2325                              <1> 	;
  2326                              <1> 	; Calling sequence:
  2327                              <1> 	;	sysmount; special
  2328                              <1> 	; Arguments:
  2329                              <1> 	;	special - special file to dismount (device)
  2330                              <1> 	;
  2331                              <1> 	; Inputs: - 
  2332                              <1> 	; Outputs: -
  2333                              <1> 	; ...............................................................
  2334                              <1> 	;				
  2335                              <1> 	; Retro UNIX 8086 v1 modification: 
  2336                              <1> 	;       'sysumount' system call has one argument; so,
  2337                              <1> 	;	* Single argument, special is pointed to by BX register
  2338                              <1> 	;
  2339                              <1> 	
  2340                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2341                              <1> 	;call	arg
  2342                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2343 00005E29 891D[C8750000]      <1>         mov	[u.namep], ebx
  2344 00005E2F E819000000          <1> 	call	getspl
  2345                              <1> 		; jsr r0,getspl / get the device number in r1
  2346 00005E34 3A05[8F750000]      <1> 	cmp	al, [mdev]
  2347                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2348 00005E3A 7529                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2349                              <1> 	;jne	error
  2350                              <1>         	; bne errora / no error
  2351 00005E3C 30C0                <1> 	xor	al, al ; ah = 0
  2352                              <1> 	; (eax = 0) ; 11/01/2022
  2353                              <1> sysumnt_0: ;1:
  2354                              <1>      	; 11/01/2022
  2355                              <1> 	;cmp 	[sb1+1], al ; 0
  2356                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2357                              <1> 	;		   ; / (inhibit bit set)?
  2358                              <1> 	;jna	short sysumnt_1		
  2359                              <1> 	;	; bne 1b / yes, wait
  2360                              <1> 	;call	idle ; (wait for hardware interrupt)
  2361                              <1> 	;jmp	short sysumnt_0
  2362                              <1> sysumnt_1:        
  2363 00005E3E A2[8F750000]        <1> 	mov	[mdev], al ; 0
  2364                              <1> 	     	; clr mntd / no, clear these
  2365 00005E43 A3[98750000]        <1>    	mov	[mnti], eax ; 11/01/2022 (eax = 0)
  2366                              <1> 	;mov	[mnti], ax ; 0
  2367                              <1>         	; clr mnti
  2368 00005E48 E91BDDFFFF          <1>         jmp	sysret
  2369                              <1> 		; br sysreta / return
  2370                              <1> 
  2371                              <1> 	; 11/01/2022 - Retro UNIX 386 v1.2
  2372                              <1> 	;	(runix v2 fs inode numbers)
  2373                              <1> getspl: ; / get device number from a special file name
  2374 00005E4D E806ECFFFF          <1> 	call	namei
  2375                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2376                              <1> 		       ; ax = 0 -> file not found 	
  2377                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2378                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2379 00005E52 7305                <1> 	jnc	short getspl_0
  2380 00005E54 E93BFFFFFF          <1> 	jmp	sysmnt_err2
  2381                              <1> getspl_0:
  2382                              <1> 	;jz	error
  2383                              <1> 	;jc	error
  2384                              <1> 		; jsr r0,namei / get the i-number of the special file
  2385                              <1>                 ; br errora / no such file
  2386                              <1>         ; 11/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode numbers)
  2387 00005E59 6683E80A            <1> 	sub	ax, 10 ; fd0 inode number = 10, hd3 inode number = 15
  2388                              <1> 		      ;	i-number-10, 0 = fd0, 5 = hd3 
  2389                              <1> 	;sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2390                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2391                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2392 00005E5D 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2393                              <1> 	;jc	error
  2394                              <1> 		; ble errora / less than 0?  yes, error
  2395 00005E5F 6683F805            <1>         cmp	ax, 5 ; 5 = hd3
  2396                              <1> 		; cmp  r1,$9. / greater than 9  tap 7
  2397                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2398                              <1> 	;;ja	error
  2399                              <1> 		; bgt errora / yes, error
  2400                              <1> 	; 11/01/2022
  2401 00005E63 760F                <1> 	jna	short getspl_retn
  2402                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2403                              <1> ;iopen_retn:
  2404                              <1> ;	retn
  2405                              <1> 		; rts    r0 / return with device number in r1
  2406                              <1> sysmnt_err0:
  2407 00005E65 C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2407 00005E6D 0000                <1>
  2408 00005E6F E9D4DCFFFF          <1> 	jmp	error
  2409                              <1> 
  2410                              <1> getspl_retn:
  2411                              <1> 	; 11/01/2022
  2412                              <1> 	; eax = Retro UNIX 386 v1 device number (0 to 5)
  2413                              <1> iopen_retn:
  2414 00005E74 C3                  <1> 	retn
  2415                              <1> 
  2416                              <1> 	; 11/02/2022
  2417                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2418                              <1> iopen:
  2419                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2420                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  2421                              <1> 	; 19/05/2015
  2422                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2423                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2424                              <1> 	;
  2425                              <1> 	; open file whose i-number is in r1
  2426                              <1> 	; 
  2427                              <1> 	; INPUTS ->
  2428                              <1> 	;    r1 - inode number
  2429                              <1> 	; OUTPUTS ->
  2430                              <1> 	;    file's inode in core	
  2431                              <1> 	;    r1 - inode number (positive)
  2432                              <1> 	;
  2433                              <1> 	; ((AX = R1))
  2434                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2435                              <1> 	;        
  2436                              <1> ; / open file whose i-number is in r1
  2437                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2438                              <1> ;		; tst r1 / write or read access?
  2439                              <1> ;       jnz	short iopen_2
  2440                              <1> ;		; blt 2f / write, go to 2f
  2441                              <1> ;	mov	dl, 2 ; read access
  2442                              <1> ;	call	access
  2443                              <1> ;       	; jsr r0,access; 2 
  2444                              <1> ;	; / get inode into core with read access
  2445                              <1> ;	; DL=2
  2446                              <1> ;iopen_0:
  2447                              <1> ;       cmp	ax, 40
  2448                              <1> ;		; cmp r1,$40. / is it a special file
  2449                              <1> ;       ja	short iopen_retn
  2450                              <1> ;		; bgt 3f / no. 3f
  2451                              <1> 
  2452                              <1> 	; 05/12/2021
  2453                              <1> 	; DL = 0 -> open for read
  2454                              <1> 	; DL = 1 -> open for write
  2455                              <1> 	; 11/02/2022
  2456                              <1> 	; DL = 2 -> create (open for write)
  2457                              <1> 		    ; (caller: syscreat)
  2458                              <1> 
  2459 00005E75 52                  <1> 	push	edx ; *
  2460                              <1> 
  2461                              <1> 	; set permission/mode flag for 'access' 
  2462                              <1> 	;	(DX = 100h -> IREAD, DX = 80h -> IWRITE)
  2463                              <1> 
  2464 00005E76 B601                <1> 	mov	dh, 1
  2465 00005E78 08D2                <1> 	or	dl, dl ; dl = 0, open for read	
  2466 00005E7A 7404                <1> 	jz	short iopen_0 ; DX = IREAD (100h)
  2467                              <1> 	; dl = 1, open for write 
  2468                              <1> 	; or
  2469                              <1> 	; dl = 2, create (regular) file	; 11/02/2022
  2470 00005E7C FECE                <1> 	dec	dh
  2471 00005E7E B280                <1> 	mov	dl, 80h
  2472                              <1> 	; DX = IWRITE (80h)
  2473                              <1> iopen_0:
  2474                              <1> 	; 27/03/2021
  2475                              <1> 	;   EAX = inode number (in AX)
  2476                              <1> 	;    DX = access mode, 100h = read, 80h = write
  2477                              <1> 
  2478                              <1> 	; 24/06/2020 - Retro UNIX 386 v2	
  2479 00005E80 E87AF7FFFF          <1> 	call	access
  2480                              <1> 		; jsr r0,access; 1 / get inode in core
  2481                              <1> 	
  2482                              <1> 	; 27/03/2021
  2483                              <1> 	; DX return value from 'access' subroutine
  2484                              <1> 	;    may be 100h, 20h, 04h for DX = 100h (IREAD) input
  2485                              <1> 	;	     80h, 10h, 02h for DX = 80h (IWRITE) input
  2486                              <1> 
  2487                              <1> 	; 05/12/2021
  2488 00005E85 5A                  <1> 	pop	edx ; * ; dl = 0 -> open for read
  2489                              <1> 			; dl = 1 -> open for write
  2490                              <1> 			; 11/02/2022
  2491                              <1> 			; dl = 2 -> create (regular) file
  2492                              <1> 			;	   (open for writing)
  2493                              <1> 	; 24/06/2020
  2494 00005E86 8A0D[59710000]      <1> 	mov	cl, [i.flgs+1]
  2495                              <1> 
  2496 00005E8C F6C180              <1> 	test	cl, 80h		; regular file ?
  2497 00005E8F 7525                <1> 	jnz	short iopen_1	; yes ; 05/12/2021
  2498 00005E91 F6C120              <1> 	test	cl, 20h 	; device file ?
  2499                              <1> 	;jnz	short iopen_2	; yes
  2500                              <1> 	; 11/02/2022
  2501 00005E94 7414                <1> 	jz	short iopen_invf ; no, invalid file/inode !
  2502                              <1> 	; device file/inode
  2503 00005E96 F6C202              <1> 	test	dl, 2 ; create file ?
  2504 00005E99 7425                <1> 	jz	short iopen_2	; device file r/w (dl=0 or dl=1)
  2505                              <1> 	; an attempt to create a file 
  2506                              <1> 	; whith name of existing device file in same directory!
  2507                              <1> iopen_pdnd:
  2508 00005E9B C705[20760000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; 11
  2508 00005EA3 0000                <1>
  2509                              <1> 				; 'permission denied !' error
  2510                              <1> iopen_err:
  2511 00005EA5 E99EDCFFFF          <1> 	jmp	error
  2512                              <1> iopen_invf:
  2513                              <1> 	; invalid inode (flags)
  2514 00005EAA C705[20760000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  2514 00005EB2 0000                <1>
  2515 00005EB4 EBEF                <1> 	jmp	short iopen_err
  2516                              <1> 
  2517                              <1> iopen_1:
  2518                              <1> 	; 05/12/2021
  2519                              <1> 	; (If open mode is 'write' and the file/inode is a directory,
  2520                              <1> 	;  open request will/must be rejected.)
  2521                              <1> 	;
  2522                              <1> 	; (If inode is a regular file and it is not a directory,
  2523                              <1> 	; there is nothing to do here, we need to return to 'sysopen'
  2524                              <1> 	; for completing the rest of file opening procedure.) 
  2525                              <1> 	
  2526 00005EB6 F6C140              <1> 	test	cl, 40h	; directory ?
  2527 00005EB9 74B9                <1> 	jz	short iopen_retn ; no
  2528                              <1> 	
  2529 00005EBB 20D2                <1> 	and	dl, dl ; open mode is 1 (write) 
  2530                              <1> 	;jz	short iopen_retn ; no
  2531                              <1> 	; 11/02/2022
  2532                              <1> 	; open mode 1 (write) or 2 (create)
  2533 00005EBD 75DC                <1> 	jnz	short iopen_pdnd ; 'permission denied !' error
  2534                              <1> ;iopen_retn:
  2535 00005EBF C3                  <1> 	retn
  2536                              <1> 
  2537                              <1> 	; !!!	
  2538                              <1> 	; 'sysopen' for writing
  2539                              <1> 	;	 is not applicable for directories
  2540                              <1> 	; (Directory entries must be created or deleted by
  2541                              <1> 	; relevant system calls.)
  2542                              <1> 
  2543                              <1> 	;;mov	dword [u.error], ERR_DIR_ACCESS ; 11
  2544                              <1> 	;mov	dword [u.error], ERR_PERM_DENIED ; 11
  2545                              <1> 	;			; 'permission denied !' error
  2546                              <1> 	;;jmp	error
  2547                              <1> 	;jmp	short iopen_err
  2548                              <1> 
  2549                              <1> ;iopen_retn:
  2550                              <1> ;	retn
  2551                              <1> 
  2552                              <1> iopen_2:
  2553                              <1> 	;push	ax
  2554                              <1> 	;	; mov r1,-(sp) / yes, figure out
  2555                              <1> 	;movzx	ebx, al
  2556                              <1> 	;shl	bx, 2
  2557                              <1> 	;	; asl r1
  2558                              <1>         ;add	ebx, iopen_1 - 4
  2559                              <1> 	;jmp	dword [ebx]
  2560                              <1>         ;	; jmp *1f-2(r1) / which one and transfer to it
  2561                              <1> 	
  2562                              <1> 	; 05/12/2021
  2563 00005EC0 50                  <1> 	push	eax ; save inode number
  2564                              <1> 	; device file
  2565 00005EC1 BB[DD5E0000]        <1> 	mov	ebx, iopen_4
  2566 00005EC6 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2567 00005EC9 720E                <1> 	jb	short iopen_3 ; null
  2568 00005ECB 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2569 00005ECE 7709                <1> 	ja	short iopen_3 ; null	
  2570                              <1> 	; convert v2 inode number to v1 device inode number
  2571 00005ED0 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2572 00005ED2 89C1                <1> 	mov	ecx, eax
  2573 00005ED4 C0E102              <1> 	shl	cl, 2 ; * 4
  2574 00005ED7 01CB                <1> 	add	ebx, ecx
  2575                              <1> iopen_3:
  2576 00005ED9 FEC2                <1> 	inc	dl ; 1 = read, 2 = write
  2577 00005EDB FF23                <1> 	jmp	dword [ebx]	
  2578                              <1> 		; jmp *1f-2(r1)
  2579                              <1> ;iopen_1: ; 1:
  2580                              <1> iopen_4:
  2581 00005EDD [1E590000]          <1> 	dd	null ; 05/12/2021
  2582 00005EE1 [2D5F0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2583                              <1>  		 ;otty / tty ; r1=2
  2584                              <1>         	 ;oppt / ppt ; r1=4
  2585 00005EE5 [E55F0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2586                              <1> 		 ;sret / mem ; r1=6
  2587                              <1> 		 ;sret / rf0
  2588                              <1>         	 ;sret / rk0
  2589                              <1>         	 ;sret / tap0
  2590                              <1>         	 ;sret / tap1
  2591                              <1>         	 ;sret / tap2
  2592                              <1>         	 ;sret / tap3
  2593                              <1>         	 ;sret / tap4
  2594                              <1>         	 ;sret / tap5
  2595                              <1>         	 ;sret / tap6
  2596                              <1>         	 ;sret / tap7
  2597 00005EE9 [E55F0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2598 00005EED [E55F0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2599 00005EF1 [E55F0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2600 00005EF5 [E55F0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2601 00005EF9 [E55F0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2602 00005EFD [E55F0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2603                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2604 00005F01 [E55F0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2605 00005F05 [3E5F0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2606                              <1> 		 ;ocvt / tty0
  2607 00005F09 [3E5F0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2608                              <1> 		 ;ocvt / tty1
  2609 00005F0D [3E5F0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2610                              <1> 		 ;ocvt / tty2
  2611 00005F11 [3E5F0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2612                              <1> 		 ;ocvt / tty3
  2613 00005F15 [3E5F0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2614                              <1> 		 ;ocvt / tty4
  2615 00005F19 [3E5F0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2616                              <1> 		 ;ocvt / tty5
  2617 00005F1D [3E5F0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2618                              <1> 		 ;ocvt / tty6
  2619 00005F21 [3E5F0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2620                              <1> 		 ;ocvt / tty7
  2621 00005F25 [3E5F0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2622                              <1> 		 ;error / crd
  2623 00005F29 [3E5F0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2624                              <1> 
  2625                              <1> ;iopen_2: ; 2: / check open write access
  2626                              <1> ;	neg	ax
  2627                              <1> ;		; neg r1 / make inode number positive
  2628                              <1> ;	mov	dl, 1 ; write access
  2629                              <1> ;	call	access
  2630                              <1> ;		; jsr r0,access; 1 / get inode in core
  2631                              <1> ;	; DL=1
  2632                              <1> ;	test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2633                              <1> ;		;bit $40000,i.flgs / is it a directory?
  2634                              <1> ;	jz	short iopen_0
  2635                              <1> ;	;mov	[u.error], ERR_DIR_ACCESS
  2636                              <1> ;	;jmp	error ; permission denied !
  2637                              <1> ;	jmp	sysmnt_err0
  2638                              <1> ;	;;jnz	error		
  2639                              <1> ;      		; bne 2f / yes, transfer (error)
  2640                              <1> ;       ;;jmp     short iopen_0
  2641                              <1> ;	;cmp	ax, 40
  2642                              <1> ;		; cmp r1,$40. / no, is it a special file?
  2643                              <1> ;        ;ja	short iopen_2
  2644                              <1> ;		; bgt 3f / no, return
  2645                              <1> ;	;push	ax
  2646                              <1> ;		; mov r1,-(sp) / yes
  2647                              <1> ;	;movzx	ebx, al
  2648                              <1> ;	;shl	bx, 1
  2649                              <1> ;		; asl r1
  2650                              <1> ;	;add	ebx, ipen_3 - 2
  2651                              <1> ;	;jmp	dword [ebx]
  2652                              <1> ;		; jmp *1f-2(r1) / figure out 
  2653                              <1> ;			; / which special file it is and transfer
  2654                              <1> ;iopen_3: ; 1:
  2655                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2656                              <1> ; 		 ;otty / tty ; r1=2
  2657                              <1> ;        	 ;leadr / ppt ; r1=4
  2658                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2659                              <1> ;		 ;sret / mem ; r1=6
  2660                              <1> ;		 ;sret / rf0
  2661                              <1> ;        	 ;sret / rk0
  2662                              <1> ;        	 ;sret / tap0
  2663                              <1> ;        	 ;sret / tap1
  2664                              <1> ;        	 ;sret / tap2
  2665                              <1> ;        	 ;sret / tap3
  2666                              <1> ;        	 ;sret / tap4
  2667                              <1> ;        	 ;sret / tap5
  2668                              <1> ;        	 ;sret / tap6
  2669                              <1> ;        	 ;sret / tap7
  2670                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2671                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2672                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2673                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2674                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2675                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2676                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2677                              <1> ;	;dd	ejec ; lpr, AX = 9  (runix)
  2678                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2679                              <1> ;		 ;ocvt / tty0
  2680                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2681                              <1> ;		 ;ocvt / tty1
  2682                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2683                              <1> ;		 ;ocvt / tty2
  2684                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2685                              <1> ;		 ;ocvt / tty3
  2686                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2687                              <1> ;		 ;ocvt / tty4
  2688                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2689                              <1> ;		 ;ocvt / tty5
  2690                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2691                              <1> ;		 ;ocvt / tty6
  2692                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2693                              <1> ;		 ;ocvt / tty7
  2694                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2695                              <1> ;		 ;/ ejec / lpr
  2696                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2697                              <1> 
  2698                              <1> otty: ;/ open console tty for reading or writing
  2699                              <1> 	; 03/03/2022
  2700                              <1> 	; 23/02/2022
  2701                              <1> 	; 22/02/2022
  2702                              <1> 	; 09/02/2022
  2703                              <1> 	; 06/02/2022
  2704                              <1> 	; 08/01/2022
  2705                              <1> 	; 01/01/2022
  2706                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2707                              <1> 	; 16/11/2015
  2708                              <1> 	; 12/11/2015
  2709                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2710                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2711                              <1> 	; 16/07/2013
  2712                              <1> 	; Retro UNIX 8086 v1 modification:
  2713                              <1> 	;  If a tty is open for read or write by
  2714                              <1> 	;     a process (u.uno), only same process can open
  2715                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2716                              <1> 	;
  2717                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2718                              <1> 	;
  2719                              <1> 
  2720 00005F2D 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2721 00005F34 8A83[D7710000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2722                              <1> 	; 13/01/2014
  2723                              <1> 	;jmp	short ottyp
  2724                              <1> 	; 23/02/2022
  2725 00005F3A 88C4                <1> 	mov	ah, al
  2726                              <1> 	; 06/02/2022
  2727 00005F3C EB06                <1> 	jmp	short otty_0
  2728                              <1> ocvt:
  2729 00005F3E 2C0A                <1> 	sub	al, 10
  2730                              <1> ;ottyp:	; (call from sysstty)
  2731                              <1> 	; 08/01/2022
  2732 00005F40 31DB                <1> 	xor	ebx, ebx
  2733                              <1> ottyp:	; 03/03/2022
  2734                              <1> 	; (ebx < 256) ; 06/02/2022
  2735                              <1> 	; 23/02/2022
  2736 00005F42 B4FF                <1> 	mov	ah, 0FFh
  2737                              <1> 	; 22/02/2022
  2738                              <1> otty_0:
  2739                              <1> 	; 09/02/2022
  2740                              <1> 	; INPUT:
  2741                              <1> 	;	DL=1 for read, DL=2 for write, DL=0 for sysstty
  2742                              <1> 	;
  2743                              <1> 	; 08/01/2022
  2744                              <1> 	; 01/01/2022
  2745                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2746                              <1> 	; 16/11/2015
  2747                              <1> 	; 12/11/2015
  2748                              <1> 	; 18/05/2015 (32 bit modifications)
  2749                              <1> 	; 06/12/2013 - 13/07/2014
  2750 00005F44 88C6                <1> 	mov	dh, al ; tty number
  2751                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2752                              <1> 	; 08/01/2022
  2753 00005F46 88C3                <1> 	mov	bl, al
  2754 00005F48 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2755                              <1> 	; 26/01/2014	
  2756 00005F4A 81C3[E4700000]      <1> 	add 	ebx, ttyl
  2757 00005F50 668B0B              <1> 	mov 	cx, [ebx]
  2758                              <1> 		   ; CL = lock value (0 or process number)
  2759                              <1> 		   ; CH = open count 
  2760 00005F53 20C9                <1> 	and 	cl, cl
  2761                              <1> 	; 13/01/2014
  2762                              <1> 	;jz 	short otty_ret
  2763                              <1> 	; 05/12/2021
  2764 00005F55 7447                <1> 	jz 	short ottys_0
  2765                              <1> 	;
  2766                              <1> 	; 16/11/2015
  2767 00005F57 3A0D[FD750000]      <1> 	cmp 	cl, [u.uno]
  2768 00005F5D 746E                <1> 	je	short ottys_3
  2769                              <1> 	;
  2770                              <1> 	; 23/02/2022
  2771                              <1> 	; (is it the console tty of the current process?)
  2772                              <1> 	; ((fast check/permit for console tty open function))
  2773 00005F5F 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2774 00005F61 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2775                              <1> 	;
  2776                              <1> 	;
  2777                              <1> 	; 22/02/2022
  2778                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2779                              <1> 	;shl 	bl, 1
  2780                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2781                              <1> 	;;movzx ebx, byte [u.uno]
  2782                              <1> 	;mov	bl, [u.uno]
  2783                              <1> 	;shl 	bl, 1
  2784                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2785                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2786                              <1> 	; 22/02/2022 (BugFix) ; *
  2787 00005F63 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2788 00005F66 D1E6                <1> 	shl 	esi, 1
  2789 00005F68 668B86[96710000]    <1> 	mov 	ax, [esi+p.pid-2]
  2790 00005F6F 96                  <1> 	xchg	esi, eax
  2791 00005F70 A0[FD750000]        <1> 	mov	al, [u.uno]
  2792 00005F75 D0E0                <1> 	shl 	al, 1
  2793 00005F77 663BB0[B6710000]    <1> 	cmp 	si, [eax+p.ppid-2]	
  2794 00005F7E 744D                <1> 	je 	short ottys_3 ; *
  2795                              <1> 	; 23/02/2022
  2796                              <1> 	; check console tty of the process
  2797                              <1> 	; (open permission must be given if the -requested- tty is
  2798                              <1> 	;  console tty of current process)
  2799 00005F80 D0E8                <1> 	shr	al, 1
  2800 00005F82 38B0[D7710000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2801 00005F88 7443                <1> 	je 	short ottys_3
  2802                              <1> 	;
  2803                              <1> 	; the tty is locked by another process
  2804                              <1> 	; except the parent process (p.ppid)
  2805                              <1>         ; 09/02/2022
  2806                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2807                              <1> 	;		; permission denied ! error
  2808                              <1> otty_err: ; 13/01/2014
  2809                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2810                              <1> 	;;jnz	error
  2811                              <1> 	; 05/12/2021
  2812                              <1> 	;jz	short otty_stc_retn
  2813                              <1> 	;jmp	error
  2814                              <1> 	; 09/02/2022
  2815 00005F8A 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2816 00005F8D 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2817                              <1> 	; iopen (dl=1 or dl=2)
  2818 00005F8F C705[20760000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2818 00005F97 0000                <1>
  2819                              <1> 			; permission denied ! error
  2820 00005F99 E9AADBFFFF          <1> 	jmp	error
  2821                              <1> ;otty_stc_retn:
  2822                              <1> 	;stc
  2823                              <1> 	;retn
  2824                              <1> ottys_0:
  2825                              <1> 	; 05/12/2021
  2826                              <1> otty_ret:
  2827                              <1> 	; 13/01/2014
  2828 00005F9E 80FE07              <1> 	cmp 	dh, 7
  2829 00005FA1 7624                <1> 	jna	short ottys_2
  2830                              <1> 	; 16/11/2015
  2831                              <1> com_port_check:
  2832 00005FA3 BE[02710000]        <1> 	mov	esi, com1p
  2833 00005FA8 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2834 00005FAB 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2835 00005FAD 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2836                              <1> ottys_1:
  2837                              <1> 	; 12/11/2015
  2838 00005FAE 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2839 00005FB1 7714                <1> 	ja	short com_port_ready
  2840                              <1> 	;
  2841                              <1> 	; 09/02/2022
  2842 00005FB3 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2843 00005FB6 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2844 00005FB8 C705[20760000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2844 00005FC0 0000                <1>
  2845                              <1> 			   ; device not ready ! error
  2846                              <1> 	;jmp	short otty_err
  2847 00005FC2 E981DBFFFF          <1> 	jmp	error	 
  2848                              <1> com_port_ready:
  2849                              <1> ottys_2:
  2850                              <1> 	; 03/03/2022
  2851                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2852                              <1> 	;jnz	short ottys_3
  2853 00005FC7 8A0D[FD750000]      <1> 	mov	cl, [u.uno]
  2854                              <1> ottys_3:
  2855 00005FCD FEC5                <1> 	inc 	ch
  2856 00005FCF 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2857                              <1> 	; 06/12/2013
  2858 00005FD2 FEC6                <1> 	inc	dh ; tty number + 1
  2859 00005FD4 BB[E2750000]        <1> 	mov	ebx, u.ttyp
  2860                              <1> 	; 13/01/2014
  2861                              <1> 	;test	dl, 2 ; open for read sign
  2862                              <1> 	;jnz	short ottys_4
  2863                              <1> 	; 05/12/2021
  2864                              <1> 	;test	dl, 2
  2865                              <1> 	;jz	short ottys_4 ; open for read
  2866                              <1> 	; 01/01/2022
  2867 00005FD9 F6C201              <1> 	test	dl, 1
  2868 00005FDC 7501                <1> 	jnz	short ottys_4 ; open for read (dl=1)
  2869                              <1> 	; dl=2 (open for write) or dl=0 (sysstty)
  2870 00005FDE 43                  <1> 	inc	ebx
  2871                              <1> ottys_4:
  2872                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2873 00005FDF 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2874                              <1> 	; 09/02/2022
  2875 00005FE1 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2876 00005FE3 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2877                              <1> sret:
  2878                              <1> 	;pop 	ax
  2879                              <1> 	; 05/12/2021
  2880 00005FE5 58                  <1> 	pop	eax
  2881                              <1> otty_retn:	; 09/02/2022
  2882                              <1> iclose_retn:	
  2883 00005FE6 C3                  <1> 	retn
  2884                              <1> 
  2885                              <1> 	;
  2886                              <1> 	; Original UNIX v1 'otty' routine:
  2887                              <1> 	;	
  2888                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2889                              <1>         ;                 / reader status reg
  2890                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2891                              <1>         ;                 / punch status reg
  2892                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2893                              <1>         ;                          / console tty buffer
  2894                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2895                              <1>         ;            / console tty
  2896                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2897                              <1>         ;             / buffer header
  2898                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2899                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2900                              <1>         ;                 / tty
  2901                              <1>         ;br     sret / ?
  2902                              <1> ;sret:
  2903                              <1> 		;clr *$ps / set processor priority to zero
  2904                              <1> ;	pop	ax
  2905                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2906                              <1> ;3:
  2907                              <1> ;	retn
  2908                              <1>         	;rts r0
  2909                              <1> 	
  2910                              <1> ;ocvt:	; < open tty >
  2911                              <1> 	; 13/01/2014
  2912                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2913                              <1> 	; 24/09/2013 consistency check -> ok
  2914                              <1> 	; 16/09/2013
  2915                              <1> 	; 03/09/2013
  2916                              <1> 	; 27/08/2013
  2917                              <1> 	; 16/08/2013
  2918                              <1> 	; 16/07/2013
  2919                              <1> 	; 27/05/2013
  2920                              <1> 	; 21/05/2013
  2921                              <1> 	;
  2922                              <1> 	; Retro UNIX 8086 v1 modification !
  2923                              <1> 	; 
  2924                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2925                              <1> 	;		(exactly different than this one)
  2926                              <1> 	;	was in 'u9.s' file.
  2927                              <1> 	;
  2928                              <1> 	; 16/07/2013
  2929                              <1> 	; Retro UNIX 8086 v1 modification:
  2930                              <1> 	;  If a tty is open for read or write by
  2931                              <1> 	;     a process (u.uno), only same process can open
  2932                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2933                              <1> 	;
  2934                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2935                              <1> 
  2936                              <1> 	; 16/09/2013
  2937                              <1> 	; sub 	al, 10
  2938                              <1> 	
  2939                              <1> 	; 06/12/2013
  2940                              <1> 	;cmp	al, 7
  2941                              <1>         ;jna	short ottyp
  2942                              <1> 	; 13/01/2014
  2943                              <1> 	;jmp	short ottyp
  2944                              <1> 
  2945                              <1> ;oppt: / open paper tape for reading or writing
  2946                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2947                              <1> ;        tstb   pptiflg / is file already open
  2948                              <1> ;        bne    2f / yes, branch
  2949                              <1> ;1:
  2950                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2951                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2952                              <1> ;               br .+4 / for paper tape input and place in free list
  2953                              <1> ;        br     1b
  2954                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2955                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2956                              <1> ;        br     sret
  2957                              <1> ;2:
  2958                              <1> ;        jmp    error / file already open
  2959                              <1> 
  2960                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2961                              <1> iclose:
  2962                              <1> 	; 09/02/2022
  2963                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2964                              <1> 	; 10/04/2021
  2965                              <1> 	; 08/04/2021
  2966                              <1> 	; 04/04/2021 - Retro UNIX 386 v2
  2967                              <1> 	; 19/05/2015
  2968                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2969                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2970                              <1> 	;
  2971                              <1> 	; close file whose i-number is in r1
  2972                              <1> 	; 
  2973                              <1> 	; INPUTS ->
  2974                              <1> 	;    r1 - inode number
  2975                              <1> 	; OUTPUTS ->
  2976                              <1> 	;    file's inode in core	
  2977                              <1> 	;    r1 - inode number (positive)
  2978                              <1> 	;
  2979                              <1> 	; ((AX = R1))
  2980                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2981                              <1> 	;        
  2982                              <1> ;;/ close file whose i-number is in r1
  2983                              <1> ;	mov	dl, 2 ; 12/01/2014
  2984                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2985                              <1> ;		;tst r1 / test i-number
  2986                              <1> ;	;jnz	short iclose_2
  2987                              <1> ;		;blt 2f / if neg., branch
  2988                              <1> ;	jz	short iclose_0 ; 30/07/2013
  2989                              <1> ;	; 16/07/2013 
  2990                              <1> ;	neg	ax ; make it positive
  2991                              <1> ;	; 12/01/2014
  2992                              <1> ;	dec	dl ; dl = 1 (open for write)
  2993                              <1> ;iclose_0:
  2994                              <1> ;	cmp	ax, 40
  2995                              <1> ;		;cmp r1,$40. / is it a special file
  2996                              <1> ;       ja	short iclose_retn  ; 13/01/2014
  2997                              <1> ;		;bgt 3b / no, return
  2998                              <1> ;	; 12/01/2014
  2999                              <1> ;	; DL=2 -> special file was opened for reading
  3000                              <1> ;	; DL=1 -> special file was opened for writing
  3001                              <1> 
  3002                              <1> 	; 04/04/2021
  3003                              <1> 	; INPUT:
  3004                              <1> 	;	(e)ax = inode number
  3005                              <1> 	;	   dl = open mode
  3006                              <1> 	;		0 = control mode
  3007                              <1> 	;		1 = read
  3008                              <1> 	;		2 = write
  3009                              <1> 	; OUTPUT:
  3010                              <1> 	;	none
  3011                              <1> 	;	(if cf=1 -> eax = error code)
  3012                              <1> 	;	(if cf=0 -> ax = inode number)
  3013                              <1> 
  3014                              <1> 	; 10/04/2021
  3015                              <1>         ; Modified registers: ebx, ecx, edx, esi, edi, (ebp) 
  3016                              <1> 
  3017                              <1> 	; 05/12/2021
  3018                              <1> 	; 08/04/2021
  3019                              <1> 
  3020 00005FE7 52                  <1> 	push	edx
  3021 00005FE8 E828F5FFFF          <1> 	call	iget
  3022 00005FED 5A                  <1> 	pop	edx 
  3023                              <1> 
  3024 00005FEE 8A0D[59710000]      <1> 	mov	cl, [i.flgs+1]
  3025                              <1> 
  3026                              <1> 	; if i.flgs bit 15 is 1, it is regular file 
  3027                              <1> 	;test	byte [i.flgs+1], 80h ; is it a special file?
  3028 00005FF4 F6C180              <1> 	test	cl, 80h ; is it a special file?
  3029 00005FF7 75ED                <1> 	jnz	short iclose_retn ; no
  3030                              <1> 
  3031                              <1> 	;; inode flags - bit 13 must be 1 
  3032                              <1> 	;test	cl, 20h ; is it a valid device inode
  3033                              <1> 	;jz	short iclose_retn ; no ; 19/01/2022
  3034                              <1> 	
  3035                              <1> 	;push	ax
  3036                              <1> 	;	;mov r1,-(sp) / yes, save r1 on stack
  3037                              <1> 	;movzx	ebx, al
  3038                              <1> 	;shl	bx, 2
  3039                              <1> 	;	; asl r1
  3040                              <1> 	;add	ebx, iclose_1 - 4
  3041                              <1> 	;jmp	dword [ebx]
  3042                              <1> 	;	; jmp *1f-2(r1) / compute jump address and transfer
  3043                              <1> 
  3044                              <1> 	; 05/12/2021
  3045 00005FF9 50                  <1> 	push	eax ; save inode number
  3046                              <1> 	; device file
  3047 00005FFA BB[14600000]        <1> 	mov	ebx, iclose_1
  3048 00005FFF 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  3049 00006002 720E                <1> 	jb	short iclose_0
  3050 00006004 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  3051 00006007 7709                <1> 	ja	short iclose_0
  3052                              <1> 	; convert v2 inode number to v1 device inode number
  3053 00006009 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  3054 0000600B 89C1                <1> 	mov	ecx, eax
  3055 0000600D C0E102              <1> 	shl	cl, 2 ; * 4
  3056 00006010 01CB                <1> 	add	ebx, ecx
  3057                              <1> iclose_0:
  3058 00006012 FF23                <1> 	jmp	dword [ebx]	
  3059                              <1> 		 ; jmp *1f-2(r1)
  3060                              <1> iclose_1: ; 1:
  3061 00006014 [1E590000]          <1> 	dd	null ; 05/12/2021
  3062 00006018 [64600000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  3063 0000601C [BF600000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  3064 00006020 [BF600000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  3065 00006024 [BF600000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  3066 00006028 [BF600000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  3067 0000602C [BF600000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  3068 00006030 [BF600000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  3069 00006034 [BF600000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  3070 00006038 [BF600000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  3071                              <1> 	;dd	error; lpr, AX = 9 (error!)
  3072                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  3073 0000603C [73600000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  3074 00006040 [73600000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  3075 00006044 [73600000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  3076 00006048 [73600000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  3077 0000604C [73600000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  3078 00006050 [73600000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  3079 00006054 [73600000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  3080 00006058 [73600000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  3081 0000605C [73600000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  3082 00006060 [73600000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  3083                              <1> 
  3084                              <1> 	; 1:
  3085                              <1> 	;        ctty   / tty
  3086                              <1> 	;        cppt   / ppt
  3087                              <1> 	;        sret   / mem
  3088                              <1> 	;        sret   / rf0
  3089                              <1> 	;        sret   / rk0
  3090                              <1> 	;        sret   / tap0
  3091                              <1> 	;        sret   / tap1
  3092                              <1> 	;        sret   / tap2
  3093                              <1> 	;        sret   / tap3
  3094                              <1> 	;        sret   / tap4
  3095                              <1> 	;        sret   / tap5
  3096                              <1> 	;        sret   / tap6
  3097                              <1> 	;        sret   / tap7
  3098                              <1> 	;        ccvt   / tty0
  3099                              <1> 	;        ccvt   / tty1
  3100                              <1> 	;        ccvt   / tty2
  3101                              <1> 	;        ccvt   / tty3
  3102                              <1> 	;        ccvt   / tty4
  3103                              <1> 	;        ccvt   / tty5
  3104                              <1> 	;        ccvt   / tty6
  3105                              <1> 	;        ccvt   / tty7
  3106                              <1> 	;        error / crd
  3107                              <1> 
  3108                              <1> ;iclose_2: ; 2: / negative i-number
  3109                              <1> 	;neg	ax
  3110                              <1> 		;neg r1 / make it positive
  3111                              <1> 	;cmp	ax, 40
  3112                              <1> 		;cmp r1,$40. / is it a special file?
  3113                              <1>         ;ja	short @b
  3114                              <1> 		;bgt 3b / no. return
  3115                              <1> 	;push	ax
  3116                              <1> 		;mov r1,-(sp)
  3117                              <1> 	;movzx	ebx, al
  3118                              <1> 	;shl	bx, 1
  3119                              <1> 		;asl r1 / yes. compute jump address and transfer
  3120                              <1> 	;add	ebx, iclose_3 - 2
  3121                              <1> 	;jmp	dword [ebx]
  3122                              <1> 		;jmp *1f-2(r1) / figure out 
  3123                              <1> ;iclose_3:
  3124                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  3125                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  3126                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  3127                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  3128                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  3129                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  3130                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  3131                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  3132                              <1> 	;;dd	sret ; lpr, AX = 9	
  3133                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  3134                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  3135                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3136                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3137                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3138                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3139                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3140                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3141                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3142                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3143                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3144                              <1> 	
  3145                              <1> 	;1:
  3146                              <1> 	;      	ctty   / tty
  3147                              <1> 	;       leadr  / ppt
  3148                              <1> 	;       sret   / mem
  3149                              <1> 	;       sret   / rf0
  3150                              <1> 	;       sret   / rk0
  3151                              <1> 	;       sret   / tap0
  3152                              <1> 	;       sret   / tap1
  3153                              <1> 	;       sret   / tap2
  3154                              <1> 	;       sret   / tap3
  3155                              <1> 	;       sret   / tap4
  3156                              <1> 	;       sret   / tap5
  3157                              <1> 	;       sret   / tap6
  3158                              <1> 	;       sret   / tap7
  3159                              <1> 	;       ccvt   / tty0
  3160                              <1> 	;       ccvt   / tty1
  3161                              <1> 	;       ccvt   / tty2
  3162                              <1> 	;       ccvt   / tty3
  3163                              <1> 	;       ccvt   / tty4
  3164                              <1> 	;       ccvt   / tty5
  3165                              <1> 	;       ccvt   / tty6
  3166                              <1> 	;       ccvt   / tty7
  3167                              <1> 	;/       ejec / lpr
  3168                              <1> 
  3169                              <1> ctty: ; / close console tty
  3170                              <1> 	; 09/02/2022
  3171                              <1> 	; 06/02/2022
  3172                              <1> 	; 08/01/2022
  3173                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3174                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3175                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3176                              <1> 	;
  3177                              <1> 	; Retro UNIX 8086 v1 modification !
  3178                              <1> 	; (DL = 2 -> it is open for reading)
  3179                              <1> 	; (DL = 1 -> it is open for writing)
  3180                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3181                              <1> 	;
  3182                              <1> 	; 06/12/2013
  3183 00006064 0FB61D[FD750000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3184 0000606B 8A83[D7710000]      <1>         mov     al, [ebx+p.ttyc-1]
  3185                              <1> 	; 13/01/2014
  3186                              <1> 	;jmp	short cttyp
  3187                              <1> 	; 06/02/2022
  3188 00006071 EB04                <1> 	jmp	short ctty_0
  3189                              <1> ccvt:
  3190 00006073 2C0A                <1> 	sub 	al, 10
  3191                              <1> cttyp:
  3192                              <1> 	; 08/01/2022
  3193 00006075 31DB                <1> 	xor	ebx, ebx
  3194                              <1> ctty_0:		; 06/02/2022
  3195                              <1> 	; 09/02/2022
  3196                              <1> 	;    DL=2 -> open for writing
  3197                              <1> 	;    DL=1 -> open for reading
  3198                              <1> 	;    DL=0 -> open for sysstty system call	
  3199                              <1> 	; 08/01/2022
  3200                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3201                              <1> 	; 18/05/2015 (32 bit modifications)
  3202                              <1> 	; 16/08/2013 - 26/01/2014
  3203                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3204                              <1> 	; 08/01/2022
  3205 00006077 88C3                <1> 	mov	bl, al
  3206 00006079 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3207                              <1> 	; 26/01/2014
  3208 0000607B 81C3[E4700000]      <1> 	add 	ebx, ttyl
  3209 00006081 88C6                <1> 	mov 	dh, al ; tty number
  3210 00006083 668B03              <1> 	mov 	ax, [ebx]
  3211                              <1> 		   ; AL = lock value (0 or process number)
  3212                              <1> 		   ; AH = open count 
  3213 00006086 20E4                <1> 	and 	ah, ah
  3214 00006088 7514                <1> 	jnz	short ctty_ret
  3215                              <1> 	; 09/02/2022
  3216 0000608A 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3217 0000608D 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3218                              <1> 	; iclose (dl=1 or dl=2)
  3219 0000608F C705[20760000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3219 00006097 0000                <1>
  3220                              <1> 			; device not open ! error
  3221                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3222 00006099 E9AADAFFFF          <1> 	jmp	error
  3223                              <1> 	; 26/01/2014
  3224                              <1> ctty_ret:
  3225 0000609E FECC                <1> 	dec 	ah ; decrease open count
  3226 000060A0 7502                <1> 	jnz	short ctty_1
  3227 000060A2 30C0                <1> 	xor	al, al ; unlock/free tty
  3228                              <1> ctty_1:
  3229 000060A4 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3230                              <1> 	;
  3231 000060A7 BB[E2750000]        <1> 	mov	ebx, u.ttyp
  3232                              <1> 	;;test	dl, 1 ; open for write sign
  3233                              <1> 	;;jz	short ctty_2
  3234                              <1> 	; 05/12/2021
  3235                              <1> 	;test	dl, 2 ; open for write sign
  3236                              <1> 	;jz	short ctty_2	
  3237                              <1> 	; 09/02/2022
  3238 000060AC F6C201              <1> 	test	dl, 1 ; open for read sign
  3239 000060AF 7501                <1> 	jnz	short ctty_2
  3240                              <1> 	; open for write (dl=0 or dl=2)
  3241 000060B1 43                  <1> 	inc	ebx
  3242                              <1> ctty_2:
  3243 000060B2 FEC6                <1> 	inc	dh ; tty number + 1
  3244 000060B4 3A33                <1> 	cmp	dh, [ebx]
  3245                              <1> 	;jne	short cret
  3246 000060B6 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3247                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3248 000060B8 C60300              <1> 	mov	byte [ebx], 0
  3249                              <1> ctty_3:
  3250                              <1> 	; 09/02/2022
  3251 000060BB 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3252 000060BD 7401                <1> 	jz	short ctty_4
  3253                              <1> cret:
  3254                              <1> 	;pop	ax
  3255                              <1> 	; 05/12/2021
  3256 000060BF 58                  <1> 	pop	eax
  3257                              <1> ctty_stc_retn:	; 09/02/2022
  3258                              <1> ctty_4:
  3259 000060C0 C3                  <1> 	retn
  3260                              <1> 
  3261                              <1> ;ctty_err: ; 13/01/2014
  3262                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3263                              <1> ;	jnz	error
  3264                              <1> ;	stc
  3265                              <1> ;	retn
  3266                              <1> 
  3267                              <1> 	; Original UNIX v1 'ctty' routine:
  3268                              <1> 	;	
  3269                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3270                              <1> 	;		;/ point r5 to the console tty buffer
  3271                              <1>         ;decb   (r5) / dec number of processes using console tty
  3272                              <1>         ;br     sret / return via sret
  3273                              <1> 
  3274                              <1> ;ccvt:	; < close tty >
  3275                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3276                              <1> 	;
  3277                              <1> 	; Retro UNIX 8086 v1 modification !
  3278                              <1> 	; 
  3279                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3280                              <1> 	;		(exactly different than this one)
  3281                              <1> 	;	was in 'u9.s' file.
  3282                              <1> 	;
  3283                              <1> 	; DL = 2 -> it is open for reading
  3284                              <1> 	; DL = 1 -> it is open for writing
  3285                              <1> 	;
  3286                              <1> 	; 17/09/2013
  3287                              <1> 	;sub 	al, 10
  3288                              <1> 	;cmp	al, 7
  3289                              <1> 	;jna	short cttyp
  3290                              <1> 	; 13/01/2014
  3291                              <1> 	;jmp	short cttyp
  3292                              <1> 
  3293                              <1> ;cppt: / close paper tape
  3294                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3295                              <1> ;1:
  3296                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3297                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3298                              <1> ;                          / and assign to free list
  3299                              <1> ;               br sret
  3300                              <1> ;        br     1b
  3301                              <1> 
  3302                              <1> ;ejec:	
  3303                              <1> ;	jmp	error
  3304                              <1> ;/ejec:
  3305                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3306                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3307                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3308                              <1> ;/       br     sret / return to caller via 'sret'
  2094                                  %include 'u8.s'      ; 11/06/2015
  2095                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2096                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2097                              <1> ; ****************************************************************************
  2098                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  2099                              <1> ; Last Modification: 09/03/2022
  2100                              <1> ; ----------------------------------------------------------------------------
  2101                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2102                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2103                              <1> ;
  2104                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2105                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2106                              <1> ; <Bell Laboratories (17/3/1972)>
  2107                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2108                              <1> ;
  2109                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2110                              <1> ;
  2111                              <1> ; ****************************************************************************
  2112                              <1> 
  2113                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2114                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2115                              <1> ;; Word 1, byte 0 = device id
  2116                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2117                              <1> ;;          bit 9 = write bit
  2118                              <1> ;;	    bit 10 = read bit	  
  2119                              <1> ;;	    bit 12 = waiting to write bit	
  2120                              <1> ;;	    bit 13 = waiting to read bit
  2121                              <1> ;;	    bit 15 = inhibit bit
  2122                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2123                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2124                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2125                              <1> ;;
  2126                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2127                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2128                              <1> ;;
  2129                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2130                              <1> ;; Word 1, Byte 0 = device id
  2131                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2132                              <1> ;;          bit 9 = write bit
  2133                              <1> ;;	    bit 10 = read bit	  
  2134                              <1> ;;	    bit 12 = waiting to write bit	
  2135                              <1> ;;	    bit 13 = waiting to read bit
  2136                              <1> ;;	    bit 15 = inhibit bit
  2137                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2138                              <1> ;;
  2139                              <1> ;; Original UNIX v1 ->
  2140                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2141                              <1> ;; Original UNIX v1 -> 
  2142                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2143                              <1> ;;
  2144                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2145                              <1> ;;
  2146                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2147                              <1> ;;          0 = fd0
  2148                              <1> ;;	    1 = fd1
  2149                              <1> ;;	    2 = hd0
  2150                              <1> ;;	    3 = hd1
  2151                              <1> ;;	    4 = hd2
  2152                              <1> ;;	    5 = hd3
  2153                              <1> 
  2154                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2155                              <1> 
  2156                              <1> 	; 08/02/2022
  2157                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2158                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2159                              <1> 	; 26/04/2013
  2160                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2161                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2162                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2163                              <1> 
  2164                              <1> 	; 08/02/2022
  2165                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2166                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2167                              <1> 	; 26/04/2013
  2168                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2169                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2170                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2171                              <1> 
  2172                              <1> bread: 
  2173                              <1> 	; 08/02/2022
  2174                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2175                              <1> 	; 14/07/2015
  2176                              <1> 	; 10/07/2015
  2177                              <1> 	; 09/06/2015
  2178                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2179                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2180                              <1> 	;	
  2181                              <1> 	; / read a block from a block structured device
  2182                              <1> 	;
  2183                              <1> 	; INPUTS ->
  2184                              <1> 	;    [u.fopf] points to the block number
  2185                              <1> 	;    CX = maximum block number allowed on device
  2186                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2187                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2188                              <1> 	;    [u.count] number of bytes to read in
  2189                              <1> 	; OUTPUTS ->
  2190                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2191                              <1> 	;    [u.fopf] points to next consecutive block to be read
  2192                              <1> 	;
  2193                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2194                              <1> 	;
  2195                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2196                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2197                              <1> 	;	is increased by 1. For example: If user/program request 
  2198                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2199                              <1> 	;  	the next block number just as 512 byte reading is done.
  2200                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2201                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2202                              <1> 	;       enough to keep byte position/offset of the disk), this
  2203                              <1> 	;	defect will not be corrected, user/program must request
  2204                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2205                              <1> 	;       for achieving correct result. In future version(s), 
  2206                              <1> 	;	this defect will be corrected by using different 
  2207                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2208                              <1> 
  2209                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2210                              <1> 			       ; / (only works on tape)
  2211                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2212                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2213                              <1> ;1:
  2214                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2215                              <1> 			    ; / maximum block # allowed on device
  2216                              <1> 		; jnb short @f
  2217                              <1> 		; bhis	1f / yes, 1f (error)
  2218                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2219                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2220                              <1> 		; mov (sp)+,r1 / return block # to r1
  2221                              <1> 		; inc r1 / bump block # to next consecutive block
  2222                              <1> 		; dec (sp) / "2-1-cold" on stack
  2223                              <1> 		; bgt 1b / 2-1-cold = 0? No, go back and read in next block
  2224                              <1> ;1:
  2225                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2226                              <1> 	;push	ecx ; **
  2227                              <1> 	; 26/04/2013
  2228                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2229 000060C1 2C03                <1> 	sub	al, 3
  2230                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2231 000060C3 A2[1F760000]        <1> 	mov	[u.brwdev], al
  2232                              <1> 	; 09/06/2015
  2233                              <1> 	;movzx	ebx, al
  2234                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2235                              <1> 	; 12/01/2022 (BugFix)
  2236 000060C8 C0E002              <1> 	shl	al, 2 ; * 4
  2237 000060CB 8B88[BE6B0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2238                              <1> bread_0:
  2239 000060D1 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2240                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2241                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2242 000060D2 8B1D[C0750000]      <1> 	mov	ebx, [u.fofp]
  2243 000060D8 8B03                <1> 	mov	eax, [ebx]
  2244 000060DA C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2245                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2246                              <1> 			       ; / block #
  2247 000060DD 39C8                <1> 	cmp	eax, ecx
  2248                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2249                              <1>        	                     ; / block number allowed
  2250                              <1> 	;jnb	error 	     ; 18/04/2013
  2251                              <1> 		; bhis error10 / yes, error
  2252                              <1> 	; 08/02/2022
  2253                              <1> 	;jb	short bread_1
  2254                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2255                              <1> 	;jmp	error
  2256 000060DF 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2257                              <1> bread_1:
  2258                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2259                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2260                              <1> 	; eAX = Block number (zero based)
  2261                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2262                              <1> preread: ;; call preread
  2263 000060E1 BF[1F760000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2264 000060E6 E890020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2265                              <1> 	;; jc 	error
  2266                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2267                              <1>         ; eAX = Block/Sector number (r1)
  2268                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2269                              <1> 	; 14/03/2013
  2270 000060EB 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2271                              <1>        		; br 1f / branch if block already in a I/O buffer
  2272 000060ED 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2273                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2274 000060F2 E8DA010000          <1> 	call	poke
  2275                              <1>         	; jsr r0,poke / perform the read
  2276                              <1> 	;;jc	error ;2 0/07/2013
  2277                              <1> ; 1:
  2278                              <1>  		; clr *$ps / ps = 0
  2279                              <1>         	; rts r0
  2280                              <1> 	; 08/02/2022
  2281 000060F7 7305                <1> 	jnc	short bread_2
  2282 000060F9 E937010000          <1> 	jmp	dskrd_err
  2283                              <1> 	;
  2284                              <1> ;; return from preread
  2285                              <1> bread_2:
  2286 000060FE 66810B0040          <1> 	or	word [ebx], 4000h 
  2287                              <1> 		; bis $40000,(r5) 
  2288                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2289                              <1> bread_3: ; 1:
  2290 00006103 66F7030024          <1> 	test	word [ebx], 2400h
  2291                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2292 00006108 7407                <1> 	jz	short bread_4
  2293                              <1> 		; beq 1f / no
  2294                              <1> 		; cmp cdev,$1 / disk or drum?
  2295                              <1> 		; ble 2f / yes
  2296                              <1> 		; tstb uquant / is the time quantum = 0?
  2297                              <1> 		; bne 2f / no, 2f
  2298                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2299                              <1> 		; jsr r0,sleep; 31. 
  2300                              <1> 			; / put process to sleep in channel 31 (tape)
  2301                              <1> 		; mov (sp)+,r5 / restore r5
  2302                              <1> 		; br 1b / go back
  2303                              <1> ; 2: / drum or disk
  2304                              <1>         ;; mov	cx, [s.wait_]+2 ;; 29/07/2013
  2305 0000610A E883EFFFFF          <1> 	call	idle
  2306                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2307 0000610F EBF2                <1> 	jmp	short bread_3
  2308                              <1>        		; br 1b
  2309                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2310 00006111 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2311                              <1> 		; bic $40000,(r5) / clear bit 14
  2312                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2313 00006116 83C308              <1> 	add	ebx, 8
  2314                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2315                              <1> 	; 09/06/2015
  2316 00006119 66833D[18760000]00  <1> 	cmp	word [u.pcount], 0
  2317 00006121 7705                <1> 	ja	short bread_5
  2318 00006123 E810F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2319                              <1> bread_5:
  2320                              <1> 	; eBX = system (I/O) buffer address
  2321 00006128 E870000000          <1> 	call	dioreg
  2322                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2323                              <1> 	; esi = start address of the transfer (in the buffer)
  2324                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2325                              <1> 	; ecx = transfer count (in bytes)
  2326                              <1> 	;
  2327                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2328                              <1> ;   / of users data
  2329 0000612D F3A4                <1> 	rep	movsb
  2330                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2331                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2332                              <1>        		; bne 1b
  2333 0000612F 59                  <1> 	pop	ecx ; **
  2334 00006130 833D[D4750000]00    <1> 	cmp	dword [u.count], 0
  2335                              <1> 		; tst u.count / done
  2336 00006137 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2337                              <1>        		; beq 1f / yes, return
  2338                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2339                              <1>        		; br bread / read some more
  2340                              <1> ; 1:
  2341 00006139 58                  <1> 	pop	eax ; ****
  2342                              <1>        		; mov (sp)+,r0
  2343 0000613A C3                  <1>         retn		; 09/06/2015
  2344                              <1> 	;jmp	ret_ 
  2345                              <1> 		;jmp ret / jump to routine that called readi
  2346                              <1> 
  2347                              <1> 	; 08/02/2022
  2348                              <1> brw_oov_err:
  2349 0000613B C705[20760000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2349 00006143 0000                <1>
  2350 00006145 E9FED9FFFF          <1> 	jmp	error
  2351                              <1> 
  2352                              <1> 	; 08/02/2022
  2353                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2354                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2355                              <1> 	; 26/04/2013
  2356                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2357                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2358                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2359                              <1> 
  2360                              <1> 	; 08/02/2022
  2361                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)				
  2362                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2363                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2364                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2365                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2366                              <1> 
  2367                              <1> bwrite: 
  2368                              <1> 	; 08/02/2022
  2369                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2370                              <1> 	; 14/07/2015
  2371                              <1> 	; 10/07/2015
  2372                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2373                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2374                              <1> 	;	
  2375                              <1> 	;; / write on block structured device
  2376                              <1> 	;
  2377                              <1> 	; INPUTS ->
  2378                              <1> 	;    [u.fopf] points to the block number
  2379                              <1> 	;    CX = maximum block number allowed on device
  2380                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2381                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2382                              <1> 	;    [u.count]	number of bytes to user desires to write
  2383                              <1> 	; OUTPUTS ->
  2384                              <1> 	;    [u.fopf] points to next consecutive block to be written into
  2385                              <1> 	;
  2386                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2387                              <1> 	;
  2388                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2389                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2390                              <1> 	;	is increased by 1. For example: If user/program request 
  2391                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2392                              <1> 	;  	the next block number just as 512 byte writing is done.
  2393                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2394                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2395                              <1> 	;       enough to keep byte position/offset of the disk), this
  2396                              <1> 	;	defect will not be corrected, user/program must request
  2397                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2398                              <1> 	;       for achieving correct result. In future version(s), 
  2399                              <1> 	;	this defect will be corrected by using different 
  2400                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2401                              <1> 
  2402                              <1>        		; jsr r0,tstdeve / test the device for an error
  2403                              <1> 	;push	ecx ; **
  2404                              <1> 	;26/04/2013
  2405                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2406 0000614A 2C03                <1> 	sub	al, 3
  2407                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2408 0000614C A2[1F760000]        <1> 	mov	[u.brwdev], al
  2409                              <1> 	; 09/06/2015
  2410                              <1> 	;movzx	ebx, al
  2411                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2412                              <1> 	; 12/01/2022 (BugFix)
  2413 00006151 C0E002              <1> 	shl	al, 2 ; * 4
  2414 00006154 8B88[BE6B0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2415                              <1> bwrite_0:
  2416 0000615A 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2417                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2418                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2419 0000615B 8B1D[C0750000]      <1> 	mov	ebx, [u.fofp]
  2420 00006161 8B03                <1> 	mov	eax, [ebx]       
  2421 00006163 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2422                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2423 00006166 39C8                <1> 	cmp	eax, ecx
  2424                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2425                              <1>        	                     ; / block number allowed
  2426                              <1> 	;jnb	error	     ; 18/04/2013
  2427                              <1> 		; bhis error10 / yes, error
  2428                              <1>      	; 08/02/2022
  2429                              <1> 	;jb	short bwrite_1
  2430                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2431                              <1> 	;jmp	error
  2432 00006168 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2433                              <1> bwrite_1:
  2434                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2435                              <1> 		; inc *u.fofp / no, increment block number
  2436                              <1> 	; 09/06/2015 - 10/07/2015
  2437 0000616A 66833D[18760000]00  <1> 	cmp	word [u.pcount], 0
  2438 00006172 7705                <1> 	ja	short bwrite_2
  2439 00006174 E8BBF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2440                              <1> bwrite_2:
  2441 00006179 BF[1F760000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2442 0000617E E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2443                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2444                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2445 00006183 E815000000          <1>         call	dioreg
  2446                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2447                              <1> 	; esi = destination address (in the buffer)
  2448                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2449                              <1> 	; ecx = transfer count (in bytes)
  2450                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2451 00006188 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2452 0000618A F3A4                <1> 	rep	movsb
  2453                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2454                              <1>        		; dec r3 / area to the I/O buffer
  2455                              <1>        		; bne 1b
  2456 0000618C E80D010000          <1> 	call	dskwr
  2457                              <1> 		; jsr r0,dskwr / write it out on the device
  2458 00006191 59                  <1> 	pop	ecx ; **
  2459 00006192 833D[D4750000]00    <1>         cmp     dword [u.count], 0
  2460                              <1> 		; tst u.count / done
  2461 00006199 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2462                              <1> 		; beq 1f / yes, 1f
  2463                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2464                              <1>        		; br bwrite / go back and write next block
  2465                              <1> ; 1:
  2466 0000619B 58                  <1> 	pop	eax ; ****
  2467                              <1>        		; mov (sp)+,r0
  2468 0000619C C3                  <1> 	retn		; 09/06/2015
  2469                              <1>         ;jmp	ret_ 
  2470                              <1> 		; jmp ret / return to routine that called writei
  2471                              <1> ;error10:
  2472                              <1> ;       jmp     error  ; / see 'error' routine
  2473                              <1> 
  2474                              <1> dioreg:
  2475                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2476                              <1> 	; 14/07/2015
  2477                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2478                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2479                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2480                              <1> 	;	
  2481                              <1> 	; bookkeeping on block transfers of data
  2482                              <1> 	;
  2483                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2484                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2485                              <1> 	; 10/07/2015
  2486                              <1> 	; * returns byte offset from beginning of current sector buffer
  2487                              <1> 	; (beginning of data) in ESI
  2488                              <1> 	;
  2489 0000619D 8B0D[D4750000]      <1> 	mov	ecx, [u.count]
  2490                              <1> 		; mov u.count,r3 / move char count to r3
  2491                              <1> 	; 08/02/2022
  2492 000061A3 31D2                <1> 	xor	edx, edx
  2493 000061A5 B602                <1> 	mov	dh, 2
  2494                              <1> 	; edx = 512
  2495 000061A7 39D1                <1> 	cmp	ecx, edx ; 512
  2496                              <1> 	;cmp 	ecx, 512
  2497                              <1> 		; cmp r3,$512. / more than 512. char?
  2498 000061A9 7602                <1> 	jna	short dioreg_0
  2499                              <1> 		; blos 1f / no, branch
  2500 000061AB 89D1                <1> 	mov	ecx, edx ; 512
  2501                              <1> 	;mov	ecx, 512
  2502                              <1> 		; mov $512.,r3 / yes, just take 512.
  2503                              <1> dioreg_0:
  2504                              <1> 	; 09/06/2015
  2505 000061AD 663B0D[18760000]    <1> 	cmp	cx, [u.pcount]
  2506 000061B4 7607                <1> 	jna	short dioreg_1
  2507 000061B6 668B0D[18760000]    <1> 	mov	cx, [u.pcount]
  2508                              <1> dioreg_1:
  2509                              <1> ; 1:
  2510 000061BD 8B15[D0750000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2511                              <1> 	        ; mov u.base,r2 / put users base in r2
  2512 000061C3 010D[D8750000]      <1> 	add	[u.nread], ecx
  2513                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2514 000061C9 290D[D4750000]      <1> 	sub	[u.count], ecx
  2515                              <1> 		; sub r3,u.count / update count
  2516 000061CF 010D[D0750000]      <1> 	add	[u.base], ecx
  2517                              <1> 		; add r3,u.base / update base
  2518                              <1> 	; 10/07/2015
  2519                              <1> 	; Retro UNIX 386 v1 - modification !
  2520                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2521                              <1> 	; (It will point to next byte position instead of next block no.)
  2522 000061D5 8B35[C0750000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2523 000061DB 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2524 000061DD 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2525 000061DF 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2526 000061E4 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2527 000061E6 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2528                              <1> 	; 09/06/2015 - 10/07/2015
  2529 000061E8 66290D[18760000]    <1> 	sub	[u.pcount], cx
  2530 000061EF 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2531 000061F5 8B3D[14760000]      <1> 	mov	edi, [u.pbase]
  2532 000061FB 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2533 00006201 01D7                <1> 	add	edi, edx
  2534 00006203 893D[14760000]      <1> 	mov	[u.pbase], edi
  2535 00006209 010D[14760000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2536 0000620F C3                  <1> 	retn
  2537                              <1> 		; rts r0 / return
  2538                              <1> 
  2539                              <1> dskrd:
  2540                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2541                              <1> 	; 18/08/2015
  2542                              <1> 	; 02/07/2015
  2543                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2544                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2545                              <1> 	;
  2546                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2547                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2548                              <1> 	; (number specified in r1) in the acquired buffer.)
  2549                              <1> 	; If the device is busy at the time dskrd is called,	
  2550                              <1> 	; dskrd calls idle.
  2551                              <1> 	; 
  2552                              <1> 	; INPUTS ->
  2553                              <1> 	;    r1 - block number
  2554                              <1> 	;    cdev - current device number 
  2555                              <1> 	; OUTPUTS ->
  2556                              <1> 	;    r5 - points to first data word in I/O buffer
  2557                              <1> 	;
  2558                              <1> 	; ((AX = R1)) input/output
  2559                              <1> 	; ((BX = R5)) output 
  2560                              <1> 	;
  2561                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2562                              <1> 	;
  2563 00006210 E859010000          <1> 	call 	bufaloc
  2564                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2565                              <1> 			       ; / get a free I/O buffer
  2566                              <1> 	;;jc	error ; 20/07/2013
  2567 00006215 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2568                              <1>        		; br 1f / branch if block already in a I/O buffer
  2569                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2570 00006217 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2571                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2572                              <1> 		               ; / I/O queue entry for buffer
  2573 0000621C E8B0000000          <1> 	call	poke
  2574                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2575                              <1> 			    ; /	bit 10=1 says read
  2576                              <1> 	; 09/06/2015
  2577                              <1> 	;jnc	short dskrd_1
  2578                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2579                              <1> 	;jmp	error
  2580                              <1> 	; 08/02/2022
  2581 00006221 7212                <1> 	jc	short dskrd_3
  2582                              <1> dskrd_1: ; 1:
  2583                              <1>        		; clr *$ps
  2584 00006223 66F7030024          <1>        	test	word [ebx], 2400h
  2585                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2586                              <1> 				; / jump to idle
  2587 00006228 7407                <1>        	jz	short dskrd_2
  2588                              <1> 		; beq 1f
  2589                              <1>         ;;mov   ecx, [s.wait_]
  2590 0000622A E863EEFFFF          <1>        	call	idle
  2591                              <1> 		; jsr r0,idle; s.wait+2
  2592 0000622F EBF2                <1> 	jmp 	short dskrd_1
  2593                              <1>        		; br 1b
  2594                              <1> dskrd_2: ; 1:
  2595 00006231 83C308              <1>         add	ebx, 8
  2596                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2597                              <1> 			  ; / just read in
  2598 00006234 C3                  <1>        	retn
  2599                              <1> 		; rts r0
  2600                              <1> dskrd_err: 
  2601                              <1> 	; 08/02/2022
  2602                              <1> 	; (jump from 'bread' error)	
  2603                              <1> dskrd_3:	
  2604                              <1> 	; 08/02/2022
  2605 00006235 803D[1F760000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2606 0000623C 7509                <1> 	jne	short dskrd_4 ; no
  2607                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2608 0000623E C605[1F760000]00    <1> 	mov	byte [u.brwdev], 0
  2609 00006245 EB0A                <1> 	jmp	short dskrd_5
  2610                              <1> dskrd_4:
  2611 00006247 C705[20760000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2611 0000624F 0000                <1>
  2612                              <1> dskrd_5:
  2613 00006251 E9F2D8FFFF          <1> 	jmp	error
  2614                              <1> 
  2615                              <1> bwslot:
  2616                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2617                              <1> 	; 10/07/2015
  2618                              <1> 	;	If the block/sector is not placed in a buffer
  2619                              <1> 	;	before 'wslot', it must be read before
  2620                              <1> 	;	it is written! (Otherwise transfer counts less
  2621                              <1> 	;	than 512 bytes will be able to destroy existing 
  2622                              <1> 	;	data on disk.)
  2623                              <1> 	;
  2624                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2625                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2626                              <1> 	; Retro UNIX 8086 v1 modification !
  2627                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2628                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2629                              <1> 	;	-> eAX = block number
  2630                              <1> 	;
  2631 00006256 E820010000          <1> 	call	bufaloc_0
  2632 0000625B 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2633                              <1> 	; 12/01/2022
  2634                              <1> 	; ebx = buffer header address
  2635                              <1> bwslot_0:
  2636                              <1> 	; 10/07/2015
  2637 0000625D 8B35[C0750000]      <1> 	mov	esi, [u.fofp]
  2638 00006263 8B06                <1> 	mov	eax, [esi]
  2639 00006265 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2640 0000626A 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2641                              <1> 		       ; recent disk data must be placed in the buffer
  2642 0000626C 813D[D4750000]0002- <1> 	cmp	dword [u.count], 512
  2642 00006274 0000                <1>
  2643 00006276 730F                <1> 	jnb	short wslot_0	
  2644                              <1> bwslot_1:
  2645 00006278 E89AFFFFFF          <1> 	call	dskrd_0
  2646                              <1> 	; 12/01/2022
  2647                              <1> 	; ebx = buffer data address = buffer header addr + 8
  2648 0000627D 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again	
  2649 00006280 EB05                <1> 	jmp 	short wslot_0
  2650                              <1> 
  2651                              <1> wslot:
  2652                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2653                              <1> 	; 		(32 bit modifications)
  2654                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2655                              <1> 	;
  2656                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2657                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2658                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2659                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2660                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2661                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2662                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2663                              <1> 	;
  2664                              <1> 	; INPUTS ->
  2665                              <1>  	;    r1 - block number
  2666                              <1> 	;    cdev - current (block/disk) device number
  2667                              <1>  	;
  2668                              <1> 	; OUTPUTS ->
  2669                              <1> 	;    bufp - bits 9 and 15 are set, 
  2670                              <1> 	;           the remainder of the word left unchanged
  2671                              <1> 	;    r5 - points to first data word in I/O buffer
  2672                              <1> 	;
  2673                              <1> 	; ((AX = R1)) input/output
  2674                              <1> 	; ((BX = R5)) output 
  2675                              <1> 	;
  2676                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2677                              <1> 
  2678 00006282 E8E7000000          <1> 	call	bufaloc
  2679                              <1> 	; 10/07/2015
  2680                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2681                              <1>         	; br 1f / word in buffer in r5
  2682                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2683                              <1>         ; eAX = Block/Sector number (r1)
  2684                              <1> wslot_0: ;1:
  2685 00006287 66F7030024          <1>      	test	word [ebx], 2400h
  2686                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2687                              <1> 				; / of I/O queue entry
  2688 0000628C 7407                <1> 	jz	short wslot_1
  2689                              <1>                 ; beq 1f / branch if 10, 13 zero (i.e., not reading, 
  2690                              <1> 		       ; / or not waiting to read)
  2691                              <1> 
  2692                              <1>         ;;mov	ecx, [s.wait_] ; 29/07/2013
  2693 0000628E E8FFEDFFFF          <1> 	call	idle
  2694                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2695                              <1>        	                     ; / idle
  2696 00006293 EBF2                <1> 	jmp	short wslot_0
  2697                              <1> 		; br 1b / till finished
  2698                              <1> wslot_1: ;1:
  2699 00006295 66810B0082          <1>         or      word [ebx], 8200h
  2700                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2701                              <1>                             	 ; / (write, inhibit bits)
  2702                              <1>        		; clr *$ps / clear processor status
  2703                              <1> dskwr_1:	; 09/03/2022
  2704 0000629A 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2705                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2706                              <1> 			  ; / for this block
  2707                              <1> ;dskwr_1:	; 08/02/2022
  2708 0000629D C3                  <1>        	retn
  2709                              <1> 		; rts r0
  2710                              <1> dskwr:
  2711                              <1> 	; 09/03/2022
  2712                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2713                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2714                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2715                              <1> 	;
  2716                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2717                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2718                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2719                              <1> 	; previously has supplied all the information required in the
  2720                              <1> 	; I/O queue entry.
  2721                              <1> 	;
  2722                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2723                              <1> 	;
  2724 0000629E 8B1D[68750000]      <1> 	mov	ebx, [bufp]
  2725 000062A4 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2726                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2727                              <1>                                   ; / bottom of queue
  2728 000062A9 E823000000          <1> 	call	poke
  2729                              <1> 	; 09/06/2015
  2730 000062AE 73EA                <1> 	jnc	short dskwr_1 ; ebx = buffer header ; 09/03/2022
  2731                              <1> 	; 08/02/2022
  2732 000062B0 803D[1F760000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2733 000062B7 7509                <1> 	jne	short dskwr_0 ; no
  2734                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2735 000062B9 C605[1F760000]00    <1> 	mov	byte [u.brwdev], 0
  2736 000062C0 EB0A                <1> 	jmp	short dskwr_2
  2737                              <1> dskwr_0:
  2738 000062C2 C705[20760000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2738 000062CA 0000                <1>
  2739                              <1> dskwr_2:
  2740 000062CC E977D8FFFF          <1> 	jmp	error
  2741                              <1> ;dskwr_1:
  2742                              <1> ;	add	ebx, 8 ; 09/03/2022
  2743                              <1> ;	; ebx = buffer data address
  2744                              <1> ;	retn
  2745                              <1> 
  2746                              <1> ;ppoke:
  2747                              <1>        		; mov $340,*$ps
  2748                              <1>        		; jsr r0,poke
  2749                              <1>        		; clr *$ps
  2750                              <1> 		; rts r0
  2751                              <1> poke:
  2752                              <1> 	; 29/11/2021 (32 bit reg push-pop)
  2753                              <1> 	; 24/10/2015
  2754                              <1> 	; 20/08/2015
  2755                              <1> 	; 18/08/2015
  2756                              <1> 	; 02/07/2015
  2757                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2758                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2759                              <1> 	;
  2760                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2761                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2762                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2763                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2764                              <1> 	;
  2765                              <1> 	; Basic I/O functions for all block structured devices
  2766                              <1> 	;
  2767                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2768                              <1> 	;
  2769                              <1> 	; 20/07/2013 modifications
  2770                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2771                              <1> 	; INPUTS -> 
  2772                              <1> 	;        (EBX = buffer header address)
  2773                              <1> 	; OUTPUTS ->
  2774                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2775                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2776                              <1> 	;		(drive not ready or r/w error!)
  2777                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2778                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2779                              <1> 	;        (also it indicates invalid buffer data)
  2780                              <1> 	;
  2781 000062D1 53                  <1> 	push	ebx
  2782                              <1>        		; mov r1,-(sp)
  2783                              <1>        		; mov r2,-(sp)
  2784                              <1>        		; mov r3,-(sp)
  2785 000062D2 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2786                              <1> 	;
  2787                              <1> 	; 09/06/2015
  2788                              <1> 	; (permit read/write after a disk R/W error)
  2789 000062D3 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2790 000062D5 B001                <1> 	mov	al, 1
  2791 000062D7 D2E0                <1> 	shl	al, cl
  2792 000062D9 8405[90750000]      <1> 	test 	al, [active] ; busy ? (error)
  2793 000062DF 7408                <1> 	jz	short poke_0
  2794 000062E1 F6D0                <1> 	not	al
  2795 000062E3 2005[90750000]      <1> 	and	[active], al ; reset busy bit for this device only
  2796                              <1> poke_0:
  2797 000062E9 BE[88750000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2798                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2799                              <1> 					 ; / I/O queue pointer
  2800                              <1> poke_1: ; 1:
  2801 000062EE 83EE04              <1>         sub	esi, 4
  2802 000062F1 8B1E                <1> 	mov	ebx, [esi]
  2803                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2804 000062F3 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2805 000062F6 F6C406              <1>        	test	ah, 06h
  2806                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2807                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2808                              <1> 			       ; / queue entry
  2809 000062F9 745C                <1>         jz      short poke_5
  2810                              <1> 		; beq 2f / branch to 2f if both are clear
  2811                              <1> 	; 31/07/2013
  2812                              <1> 	;test	ah, 0B0h ; (*)
  2813                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2814                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2815                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2816                              <1> 		; bne 2f / branch if any are set
  2817                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2818                              <1>     		; movb (r1),r3 / get device id
  2819 000062FB 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2820                              <1> 	;mov	edi, ecx ; 26/04/2013
  2821 000062FE 31C0                <1> 	xor 	eax, eax ; 0
  2822                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2823                              <1> 		; tstb deverr(r3) / test for errors on this device
  2824                              <1>        	;jna	short poke_2 
  2825                              <1> 		; beq 3f / branch if no errors
  2826                              <1> 	; 02/07/2015
  2827                              <1> 	;dec	eax
  2828                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2829                              <1>        		; mov $-1,2(r1) / destroy associativity
  2830                              <1> 	;shr	eax, 24
  2831                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2832                              <1> 		; clrb 1(r1) / do not do I/O
  2833                              <1> 	;jmp	short poke_5
  2834                              <1>         ;       ; br 2f
  2835                              <1>                 ; rts r0
  2836                              <1> poke_2: ; 3:
  2837                              <1> 	; 02/07/2015
  2838 00006300 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2839 00006302 7453                <1> 	jz	short poke_5
  2840 00006304 FEC0                <1> 	inc	al ; mov ax, 1
  2841 00006306 FEC9                <1> 	dec	cl
  2842 00006308 7402                <1> 	jz	short poke_3
  2843                              <1> 	; 26/04/2013 Modification
  2844                              <1> 	;inc	al ; mov ax, 1
  2845                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2846                              <1> 	;jz	short poke_3 ; cl = 0
  2847 0000630A D2E0                <1> 	shl	al, cl ; shl ax, cl
  2848                              <1> poke_3:
  2849                              <1> 	;test	[active], ax
  2850 0000630C 8405[90750000]      <1> 	test	[active], al
  2851                              <1> 		; bit $2,active / test disk busy bit
  2852 00006312 7543                <1> 	jnz     short poke_5
  2853                              <1> 		; bne 2f / branch if bit is set
  2854                              <1> 	;or	[active], ax
  2855 00006314 0805[90750000]      <1> 	or	[active], al
  2856                              <1> 		; bis $2,active / set disk busy bit
  2857 0000631A 50                  <1> 	push	eax ; 29/11/2021
  2858 0000631B E8D1000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2859                              <1> 	;mov    [edi+drv.error], ah
  2860 00006320 58                  <1> 	pop	eax
  2861 00006321 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2862                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2863                              <1> 	;jna	short poke_4
  2864                              <1> 		; tstb deverr(r3) / test for errors on this device
  2865                              <1>        		; beq 3f / branch if no errors
  2866                              <1> 	; 02/07/2015 (32 bit modification)
  2867                              <1> 	; 20/07/2013
  2868 00006323 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2869                              <1>        		; mov $-1,2(r1) / destroy associativity
  2870 0000632A 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2871                              <1> 		; clrb 1(r1) / do not do I/O
  2872 0000632F EB26                <1> 	jmp     short poke_5
  2873                              <1> poke_4:	; 20/07/2013
  2874                              <1> 	; 17/07/2013
  2875 00006331 F6D0                <1> 	not 	al 
  2876 00006333 2005[90750000]      <1> 	and	[active], al ; reset, not busy
  2877                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2878                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2879 00006339 668B03              <1> 	mov	ax, [ebx]
  2880                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2881 0000633C 66250006            <1>         and	ax, 600h
  2882                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2883 00006340 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2884                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2885 00006345 C0E403              <1> 	shl	ah, 3
  2886                              <1>        		; rol r3
  2887                              <1>                 ; rol r3
  2888                              <1>                 ; rol r3	
  2889 00006348 660903              <1> 	or	[ebx], ax
  2890                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2891                              <1> 			   ; bits 12 and 13
  2892 0000634B E842EDFFFF          <1> 	call	idle ; 18/01/2014
  2893                              <1> 	;; sti
  2894                              <1> 	;hlt 	; wait for a hardware interrupt
  2895                              <1> 	;; cli
  2896                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2897                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2898                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2899                              <1> 	; method, this procedure will wait for a time according to
  2900                              <1> 	; multi tasking and time sharing concept.
  2901                              <1> 	;
  2902                              <1> 	; 24/10/2015
  2903                              <1> 	;not	ax 
  2904 00006350 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2905 00006354 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2906                              <1> poke_5: ;2:
  2907 00006357 81FE[68750000]      <1>         cmp     esi, bufp
  2908                              <1> 		; cmp r2,$bufp / test to see if entire I/O queue 
  2909                              <1>                             ; / has been scanned
  2910 0000635D 778F                <1> 	ja      short poke_1
  2911                              <1> 		; bhi 1b
  2912                              <1> 	; 24/03/2013
  2913                              <1>        		; mov (sp)+,r3
  2914                              <1>        		; mov (sp)+,r2
  2915                              <1>        		; mov (sp)+,r1
  2916 0000635F 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2917 00006360 5B                  <1> 	pop 	ebx
  2918                              <1> 	; 02/07/2015 (32 bit modification)
  2919                              <1> 	; 20/07/2013
  2920                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2921 00006361 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2922                              <1> 	;	
  2923                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2924                              <1> 	; or written successfully; even if an error occurs while
  2925                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2926                              <1> 	;
  2927                              <1> 	; 09/06/2015
  2928 00006364 F5                  <1> 	cmc
  2929 00006365 C3                  <1> 	retn
  2930                              <1>                 ; rts r0
  2931                              <1> 
  2932                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatibility code
  2933                              <1> get_system_time:
  2934                              <1> 	; 27/10/2021
  2935                              <1> 	; 21/02/2020 - Retro UNIX 386 v2
  2936                              <1> 	; get system time
  2937                              <1> 	;  (from recent value which is saved in RTC interrupt)
  2938                              <1> 	; Input:
  2939                              <1> 	; 	none
  2940                              <1> 	; Return:
  2941                              <1> 	;   	eax = system time in unix epoch format 
  2942                              <1> 	;
  2943                              <1> 	; Modified registers: eax, ecx, edx
  2944                              <1> 	
  2945                              <1> 	; 27/11/2021
  2946 00006366 53                  <1> 	push	ebx
  2947 00006367 E8A7D2FFFF          <1> 	call	epoch
  2948 0000636C 5B                  <1> 	pop	ebx
  2949 0000636D C3                  <1> 	retn
  2950                              <1> 	
  2951                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2952                              <1> 	;  ('get_serial_number' is not used in v1.2 kernel)
  2953                              <1> ;get_serial_number:
  2954                              <1> 	; temporary - 21/02/2020
  2955                              <1> 	; 26/04/2020 (esi)
  2956                              <1> 	; 25/04/2020
  2957                              <1> 	; (Possible) Modified registers: eax, ecx, edx
  2958                              <1> 	; (edi, ebx & esi registers must be preserved)
  2959                              <1> 	; Return:
  2960                              <1> 	; eax = 32 bit serial number  
  2961                              <1> 	; (edx = high 32 bit of 64 bit serial number)
  2962                              <1> 	; -64 bit serial numbers will not be used in RUNIX 386 v2-
  2963                              <1> 	
  2964                              <1> 	;retn
  2965                              <1> 
  2966                              <1> bufaloc:
  2967                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2968                              <1> 	; 20/08/2015
  2969                              <1> 	; 19/08/2015
  2970                              <1> 	; 02/07/2015
  2971                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2972                              <1> 	;	     (32 bit modifications)	
  2973                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2974                              <1> 	;
  2975                              <1> 	; bufaloc - Block device I/O buffer allocation
  2976                              <1> 	; 
  2977                              <1> 	; INPUTS ->
  2978                              <1> 	;    r1 - block number
  2979                              <1> 	;    cdev - current (block/disk) device number
  2980                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2981                              <1> 	; OUTPUTS ->
  2982                              <1> 	;    r5 - pointer to buffer allocated
  2983                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2984                              <1> 	;
  2985                              <1> 	; ((AX = R1)) input/output
  2986                              <1> 	; ((BX = R5)) output
  2987                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2988                              <1> 	;    zf=1 -> block already in a I/O buffer
  2989                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2990                              <1> 	;    ((DL = Device ID))
  2991                              <1> 	;    (((DH = 0 or 1)))
  2992                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2993                              <1> 	;    ((CX and DH will not be used after return)))
  2994                              <1> 
  2995                              <1> 	;;push 	esi ; ***
  2996                              <1> 		; mov r2,-(sp) / save r2 on stack
  2997                              <1>        		; mov $340,*$ps / set processor priority to 7
  2998                              <1> 	; 20/07/2013
  2999                              <1> 	; 26/04/2013
  3000                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  3001                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  3002                              <1> 	;add	edi, ebx
  3003                              <1> 	; 09/01/2022
  3004 0000636E 0FB63D[8D750000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  3005 00006375 81C7[8E750000]      <1> 	add	edi, rdev
  3006                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  3007                              <1> 			;; eDI points to device id.
  3008 0000637B 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  3009                              <1> 	; 11/06/2021
  3010 0000637E 80BB[DA6B0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  3011 00006385 720F                <1> 	jb	short bufaloc_9
  3012 00006387 C705[20760000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3012 0000638F 0000                <1>
  3013 00006391 E9B2D7FFFF          <1> 	jmp	error
  3014                              <1> bufaloc_9:
  3015 00006396 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  3016                              <1> bufaloc_10: ; 02/07/2015
  3017 00006398 31ED                <1> 	xor 	ebp, ebp ; 0
  3018 0000639A 55                  <1> 	push	ebp ; 0
  3019 0000639B 89E5                <1>         mov     ebp, esp	
  3020                              <1> 	;
  3021                              <1> bufaloc_1: ;1:
  3022                              <1> 		; clr -(sp) / vacant buffer
  3023 0000639D BE[68750000]        <1>         mov 	esi, bufp
  3024                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3025                              <1> 			     ; / entrys in buffer area
  3026                              <1> bufaloc_2: ;2:
  3027 000063A2 8B1E                <1> 	mov	ebx, [esi]
  3028                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3029                              <1> 			    ; queue entry into r5
  3030 000063A4 66F70300F6          <1> 	test	word [ebx], 0F600h
  3031                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3032 000063A9 7503                <1>         jnz	short bufaloc_3
  3033                              <1> 		; bne 3f / branch when 
  3034                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3035                              <1>                        ; / (i.e., buffer busy)
  3036 000063AB 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  3037                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  3038                              <1> 			; / found points to word 2 of I/O queue entry)
  3039                              <1> bufaloc_3: ;3:
  3040                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3041                              <1> 	;
  3042 000063AE 3813                <1> 	cmp	[ebx], dl	
  3043                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3044                              <1> 			       ; / as current device
  3045 000063B0 7508                <1> 	jne	short bufaloc_4
  3046                              <1>        		; bne 3f
  3047 000063B2 394304              <1> 	cmp	[ebx+4], eax
  3048                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3049                              <1> 			     ; / same as current block number
  3050 000063B5 7503                <1>        	jne	short bufaloc_4
  3051                              <1> 		; bne 3f
  3052                              <1> 	;add	esp, 4
  3053 000063B7 59                  <1> 	pop	ecx
  3054                              <1>        		; tst (sp)+ / bump stack pointer
  3055 000063B8 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3056                              <1> 				; jump to bufaloc_6 in original Unix v1
  3057                              <1>        		; br 1f / use this buffer
  3058                              <1> bufaloc_4: ;3:
  3059 000063BA 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3060                              <1> 	;
  3061 000063BD 81FE[80750000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3062                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3063 000063C3 72DD                <1> 	jb	short bufaloc_2
  3064                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3065                              <1>                        ; / buffers not checked)
  3066 000063C5 5E                  <1>         pop	esi
  3067                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3068                              <1> 			     ; / to last free block
  3069 000063C6 09F6                <1>        	or	esi, esi 
  3070 000063C8 7507                <1> 	jnz	short bufaloc_5
  3071                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3072                              <1> 	        ; / if a free buffer is found branch to 2f
  3073                              <1>         ;; mov  ecx, [s.wait_]
  3074 000063CA E8C3ECFFFF          <1> 	call	idle
  3075                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  3076 000063CF EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3077                              <1>        		; br 1b
  3078                              <1> bufaloc_5: ;2:
  3079                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3080 000063D1 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3081                              <1> bufaloc_6: ;1:
  3082 000063D3 8B1E                <1>         mov    	ebx, [esi] 
  3083                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3084                              <1> 			     ; / entry in r5
  3085                              <1> 	;; 26/04/2013
  3086                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3087 000063D5 8813                <1> 	mov 	[ebx], dl
  3088                              <1> 		; movb cdev,(r5) / put current device number 
  3089                              <1> 				 ; / in I/O queue entry
  3090 000063D7 894304              <1> 	mov 	[ebx+4], eax
  3091                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3092                              <1> 			     ; / of I/O queue entry
  3093                              <1> bufaloc_7: ;1:
  3094 000063DA 81FE[68750000]      <1>         cmp	esi, bufp
  3095                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3096                              <1> 			     ; / and put latest assigned
  3097 000063E0 760A                <1> 	jna	short bufaloc_8	
  3098                              <1>        		; blos 1f / buffer on the top 
  3099                              <1> 			; / (this makes if the lowest priority)
  3100 000063E2 83EE04              <1> 	sub	esi, 4
  3101 000063E5 8B0E                <1> 	mov	ecx, [esi]
  3102 000063E7 894E04              <1> 	mov	[esi+4], ecx
  3103                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3104 000063EA EBEE                <1> 	jmp 	short bufaloc_7        
  3105                              <1> 		; br 1b
  3106                              <1> bufaloc_8: ;1:
  3107 000063EC 891E                <1>         mov	[esi], ebx
  3108                              <1> 		; mov r5,(r2)
  3109                              <1> 	;;pop	esi ; ***
  3110                              <1>        		; mov (sp)+,r2 / restore r2
  3111 000063EE 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3112                              <1> 		; Retro UNIX 8086 v1 modification
  3113                              <1> 		; zf=1 --> block already is in an I/O buffer
  3114                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3115 000063F0 C3                  <1> 	retn
  3116                              <1> 		; rts r0
  3117                              <1> 
  3118                              <1> diskio:
  3119                              <1> 	; 12/02/2022
  3120                              <1> 	; 10/02/2022
  3121                              <1> 	; 08/02/2022
  3122                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3123                              <1> 	; 28/11/2021
  3124                              <1> 	; 10/07/2015
  3125                              <1> 	; 02/07/2015
  3126                              <1> 	; 16/06/2015
  3127                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3128                              <1> 	;	     (80386 protected mode modifications)	
  3129                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3130                              <1> 	;
  3131                              <1> 	; Retro UNIX 8086 v1 feature only !
  3132                              <1> 	;
  3133                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3134                              <1> 	; 04/07/2009 - 20/07/2011
  3135                              <1> 	;
  3136                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3137                              <1> 	;
  3138                              <1>         ; INPUTS ->
  3139                              <1> 	; 	   ebx = System I/O Buffer header address
  3140                              <1> 	;
  3141                              <1>         ; OUTPUTS -> cf=0 --> done 
  3142                              <1> 	; 	     cf=1 --> error code in AH
  3143                              <1> 	;	     ; 08/02/2022
  3144                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3145                              <1> 	;		error code in [u.error]
  3146                              <1> 	;		
  3147                              <1> 	; (Modified registers: eax, ecx, edx)
  3148                              <1> 	
  3149                              <1> ;rw_disk_sector:
  3150                              <1> 	; 12/02/2022
  3151                              <1> 	; 10/02/2022
  3152                              <1> 	; 08/02/2022
  3153                              <1> 	; 28/11/2021
  3154                              <1> 	; 10/07/2015
  3155                              <1> 	; 02/07/2015
  3156                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3157                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3158                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3159                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3160                              <1> 	;
  3161                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3162 000063F1 B602                <1> 	mov	dh, 2
  3163                              <1> 	;mov	ax, [ebx]
  3164                              <1> 	; 28/11/2021
  3165 000063F3 8B03                <1> 	mov	eax, [ebx]
  3166                              <1> 	;
  3167 000063F5 56                  <1> 	push	esi ; ****
  3168 000063F6 53                  <1> 	push	ebx ; ***
  3169                              <1> 	;
  3170 000063F7 0FB6C8              <1> 	movzx	ecx, al
  3171                              <1> 	; 28/11/2021
  3172                              <1> 	;mov	ecx, eax
  3173 000063FA 89CE                <1> 	mov	esi, ecx
  3174                              <1> 	;
  3175 000063FC 38F1                <1> 	cmp	cl, dh ; 2
  3176 000063FE 7202                <1> 	jb	short rwdsk0
  3177 00006400 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3178                              <1> rwdsk0:
  3179 00006402 A2[8B6B0000]        <1> 	mov	[drv], al
  3180 00006407 81C6[DA6B0000]      <1> 	add	esi, drv.status
  3181                              <1> 	; 11/06/2015
  3182 0000640D 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3183 00006410 7204                <1> 	jb      short rwdsk1
  3184                              <1> 	; 'drive not ready' error
  3185                              <1> 	; 10/02/2022
  3186                              <1> 	; 08/02/2022
  3187                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3188                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3189                              <1> 	;;jmp	error
  3190                              <1> 	;stc	; cf = 1
  3191                              <1> 	;retn
  3192                              <1> 	; 10/02/2022
  3193 00006412 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3194 00006414 EB20                <1> 	jmp	short rwdsk_err1
  3195                              <1> rwdsk1:
  3196 00006416 F6C402              <1> 	test	ah, 2
  3197                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3198                              <1> 			 ; write bit
  3199 00006419 7402                <1> 	jz	short rwdsk2
  3200                              <1> 	;test	ah, 4
  3201                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3202                              <1> 	;		 ; read bit
  3203                              <1> 	;jz	short diskio_ret
  3204 0000641B FEC6                <1> 	inc	dh ; 03h = write
  3205                              <1> rwdsk2:
  3206 0000641D 88C2                <1> 	mov	dl, al
  3207 0000641F 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3208 00006422 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3209 00006424 C0E102              <1> 	shl	cl, 2
  3210 00006427 81C1[BE6B0000]      <1> 	add	ecx, drv.size ; disk size
  3211 0000642D 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3212 0000642F 7214                <1> 	jb      short rwdsk3
  3213                              <1>  	; 'out of volume' error
  3214                              <1> 	; 10/02/2022
  3215                              <1> 	; 08/02/2022
  3216                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3217                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3218                              <1> 	;;jmp	error
  3219                              <1> 	;stc	; cf = 1
  3220                              <1> 	;retn
  3221                              <1> 	; 10/02/2022
  3222 00006431 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3223                              <1> rwdsk_err1:
  3224 00006436 C605[1F760000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3225 0000643D 890D[20760000]      <1> 	mov	[u.error], ecx ; 12/02/2022
  3226 00006443 EB30                <1> 	jmp	short rwdsk_err2
  3227                              <1> rwdsk3:
  3228                              <1> 	; 11/06/2015
  3229 00006445 83C304              <1> 	add	ebx, 4 ; buffer address
  3230 00006448 C605[43760000]04    <1> 	mov	byte [retry_count], 4
  3231 0000644F F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3232 00006452 7432                <1>         jz      short rwdsk_chs
  3233                              <1> rwdsk_lba:
  3234                              <1> 	; LBA read/write (with private LBA function) 
  3235                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3236 00006454 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3237 00006457 89C1                <1> 	mov	ecx, eax ; sector number
  3238                              <1> 	; ebx = buffer (data) address
  3239                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3240                              <1> rwdsk_lba_retry:
  3241                              <1> 	;mov	dl, [drv]
  3242                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3243 00006459 B419                <1> 	mov	ah, 1Ch - 03h ; LBA write function number - 3
  3244 0000645B 00F4                <1> 	add	ah, dh		
  3245 0000645D B001                <1> 	mov	al, 1
  3246                              <1> 	;int	13h
  3247 0000645F E836C1FFFF          <1> 	call	int13h
  3248 00006464 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3249 00006466 730E                <1> 	jnc	short rwdsk_lba_ok
  3250 00006468 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3251 0000646B 7408                <1>         je      short rwdsk_lba_fails
  3252 0000646D FE0D[43760000]      <1> 	dec	byte [retry_count]
  3253 00006473 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3254                              <1> rwdsk_err2:	; 10/02/2022
  3255                              <1> rwdsk_lba_fails:
  3256 00006475 F9                  <1> 	stc
  3257                              <1> rwdsk_lba_ok:
  3258 00006476 5B                  <1> 	pop	ebx ; ***
  3259 00006477 5E                  <1> 	pop	esi ; ****
  3260 00006478 C3                  <1> 	retn
  3261                              <1> rwdsk_lba_reset:
  3262 00006479 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3263                              <1> 	;int	13h
  3264 0000647B E81AC1FFFF          <1>         call	int13h
  3265 00006480 73D7                <1> 	jnc     short rwdsk_lba_retry
  3266 00006482 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3267 00006484 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3268                              <1> 	;
  3269                              <1> 	; CHS read (convert LBA address to CHS values)	
  3270                              <1> rwdsk_chs:
  3271                              <1> 	; 10/07/2015
  3272 00006486 81EE[DA6B0000]      <1> 	sub	esi, drv.status
  3273 0000648C 89F1                <1> 	mov	ecx, esi
  3274 0000648E 81C6[E16B0000]      <1> 	add 	esi, drv.error
  3275                              <1> 	; 02/07/2015
  3276                              <1> 	; 16/06/2015
  3277                              <1>  	; 11/06/2015 
  3278 00006494 53                  <1> 	push	ebx ; ** ; buffer
  3279 00006495 D1E1                <1> 	shl	ecx, 1
  3280 00006497 51                  <1> 	push	ecx ; * 
  3281                              <1> 	;
  3282 00006498 89CB                <1> 	mov	ebx, ecx
  3283 0000649A 8835[41760000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3284 000064A0 31D2                <1> 	xor	edx, edx ; 0
  3285                              <1> 	; 09/01/2022
  3286                              <1> 	;sub	ecx, ecx 
  3287 000064A2 81C3[B06B0000]      <1>         add     ebx, drv.spt
  3288 000064A8 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3289                              <1> 		; EDX:EAX = LBA
  3290 000064AB F7F1                <1> 	div	ecx
  3291 000064AD 88D1                <1> 	mov	cl, dl	; sector number - 1
  3292 000064AF FEC1                <1> 	inc	cl	; sector number (1 based)
  3293 000064B1 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3294                              <1> 	;push	cx
  3295 000064B2 51                  <1> 	push	ecx ; 28/11/2021
  3296 000064B3 81C3[A26B0000]      <1>         add     ebx, drv.heads
  3297 000064B9 668B0B              <1> 	mov	cx, [ebx] ; heads
  3298 000064BC 31D2                <1> 	xor	edx, edx
  3299                              <1> 		; EAX = cylinders * heads + head
  3300 000064BE F7F1                <1> 	div	ecx
  3301                              <1> 	;pop	cx     ; sector number
  3302 000064C0 59                  <1> 	pop	ecx ; 28/11/2021
  3303 000064C1 88D6                <1> 	mov	dh, dl ; head number
  3304 000064C3 8A15[8B6B0000]      <1> 	mov	dl, [drv]
  3305 000064C9 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3306 000064CB C0E406              <1> 	shl	ah, 6
  3307 000064CE 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3308                              <1> 		       ; sector (bits 0-7)
  3309 000064D0 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3310                              <1> 		; CL = sector (bits 0-5)
  3311                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3312                              <1> 		; CH = cylinder (bits 0-7)
  3313                              <1> 		; DH = head
  3314                              <1> 		; DL = drive
  3315                              <1> 	;
  3316 000064D1 C605[43760000]04    <1> 	mov	byte [retry_count], 4
  3317                              <1> rwdsk_retry:	
  3318 000064D8 8A25[41760000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3319 000064DE B001                <1> 	mov	al, 1 ; sector count	
  3320                              <1> 	;int	13h
  3321 000064E0 E8B5C0FFFF          <1> 	call	int13h
  3322 000064E5 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3323 000064E7 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3324 000064E9 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3325 000064EC 7408                <1> 	je	short rwdsk_fails
  3326 000064EE FE0D[43760000]      <1> 	dec	byte [retry_count]
  3327 000064F4 7504                <1> 	jnz	short rwdsk_reset
  3328                              <1> rwdsk_fails:
  3329 000064F6 F9                  <1> 	stc
  3330                              <1> rwdsk_ok:
  3331 000064F7 5B                  <1> 	pop	ebx ; ***
  3332 000064F8 5E                  <1> 	pop	esi ; ****
  3333 000064F9 C3                  <1> 	retn
  3334                              <1> rwdsk_reset:
  3335                              <1> 	; 02/02/2015
  3336 000064FA 28E4                <1> 	sub	ah, ah
  3337 000064FC 80FA80              <1> 	cmp	dl, 80h
  3338 000064FF 7202                <1> 	jb	short rwdsk_fd_reset
  3339 00006501 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3340                              <1> rwdsk_fd_reset:
  3341                              <1> 	;int	13h
  3342 00006503 E892C0FFFF          <1>         call	int13h
  3343 00006508 73CE                <1> 	jnc	short rwdsk_retry
  3344 0000650A 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3345 0000650C EBE9                <1> 	jmp 	short rwdsk_ok
  3346                              <1> 
  3347                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3348                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3349                              <1> ;
  3350                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3351                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3352                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3353                              <1> ; that uses hardware -transfer has been completed- interrupt inside it. 
  3354                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3355                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3356                              <1> ; as in original unix v1.
  3357                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3358                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3359                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3360                              <1> ;
  3361                              <1> ; Erdogan tan (10/07/2015) 
  3362                              <1> 
  3363                              <1> ;drum: / interrupt handler
  3364                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3365                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3366                              <1> ;                                      / error
  3367                              <1> ;               br 3f / no, error
  3368                              <1> ;       br      2f / error
  3369                              <1> ;
  3370                              <1> ;disk:
  3371                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3372                              <1> ;       jmp     *$0f
  3373                              <1> ;0:
  3374                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3375                              <1> ;      	        br 3f / no, errors
  3376                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3377                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3378                              <1> ;                        / to 1f
  3379                              <1> ;       br      4f
  3380                              <1> ;1:
  3381                              <1> ;       bit     $20000,rkcs
  3382                              <1> ;       beq     4f / wait for seek complete
  3383                              <1> ;       mov     $0b,0b-2
  3384                              <1> ;       mov     rkap,r1
  3385                              <1> ;2:
  3386                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3387                              <1> ;                          / the disk buffer
  3388                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3389                              <1> ;       inc     r1
  3390                              <1> ;       asr     (r1)
  3391                              <1> ;       asr     (r1)
  3392                              <1> ;       asr     (r1) / reissue request
  3393                              <1> ;       dec     r1
  3394                              <1> ;3:
  3395                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3396                              <1> ;       mov     ac,-(sp)
  3397                              <1> ;       mov     mq,-(sp) / put these on the stack
  3398                              <1> ;       mov     sc,-(sp)
  3399                              <1> ;       jsr     r0,poke
  3400                              <1> ;       mov     (sp)+,sc
  3401                              <1> ;       mov     (sp)+,mq / pop them off stack
  3402                              <1> ;       mov     (sp)+,ac
  3403                              <1> ;4:
  3404                              <1> ;       jmp     retisp / u4-3
  3405                              <1> ;
  3406                              <1> ;trapt:                  / r2 points to the
  3407                              <1> ;       mov     (r0)+,r2 / device control register
  3408                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3409                              <1> ;       tst     (sp)+
  3410                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3411                              <1> ;       bge     4b / device still active so branch
  3412                              <1> ;       bit     (r0),active / was device busy?
  3413                              <1> ;       beq     4b / no, stray interrupt
  3414                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3415                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3416                              <1> ;       bge     2f / if no error jump to 2f
  3417                              <1> ;       tst     (r0)+ / skip on error
  3418                              <1> ; 2:
  3419                              <1> ;       jmp     (r0)
  2095                                  %include 'u9.s'      ; 29/06/2015
  2096                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2097                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2098                              <1> ; ****************************************************************************
  2099                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS9.INC
  2100                              <1> ; Last Modification: 16/02/2022
  2101                              <1> ; ----------------------------------------------------------------------------
  2102                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2103                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2104                              <1> ;
  2105                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2106                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2107                              <1> ; <Bell Laboratories (17/3/1972)>
  2108                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2109                              <1> ;
  2110                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2111                              <1> ;
  2112                              <1> ; ****************************************************************************
  2113                              <1> 
  2114                              <1> getch:
  2115                              <1> 	; 30/06/2015
  2116                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2117 0000650E 28C0                <1> 	sub	al, al ; 0
  2118                              <1> getch_q: ; 06/08/2015
  2119 00006510 8A25[C6700000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2120 00006516 EB06                <1>         jmp     short getc_n
  2121                              <1> 
  2122                              <1> getc: 
  2123                              <1> 	; 12/11/2015
  2124                              <1> 	; 15/09/2015
  2125                              <1> 	; 01/07/2015
  2126                              <1> 	; 30/06/2015
  2127                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2128                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2129                              <1> 	;
  2130                              <1> 	; Retro UNIX 8086 v1 modification !
  2131                              <1> 	; 
  2132                              <1> 	; 'getc' gets (next) character 
  2133                              <1> 	;	 from requested TTY (keyboard) buffer 
  2134                              <1> 	; INPUTS ->
  2135                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2136                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2137                              <1> 	;	(Keyboard buffer will point to 
  2138                              <1> 	;			next character at next call)
  2139                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2140                              <1> 	;	(Keyboard buffer will point to 
  2141                              <1> 	;			current character at next call)
  2142                              <1> 	; OUTPUTS ->
  2143                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2144                              <1> 	;     			 ZF=0 -> AX has (current) character
  2145                              <1> 	;      AL = ascii code
  2146                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2147                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2148                              <1> 	; Original UNIX V1 'getc': 
  2149                              <1> 	;		get a character off character list
  2150                              <1> 	;
  2151                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2152                              <1> 	;
  2153                              <1> 	; 30/06/2015 (32 bit modifications)
  2154                              <1> 	; 16/07/2013
  2155                              <1> 	; mov 	[getctty], ah
  2156                              <1> 	;
  2157                              <1> 
  2158 00006518 8A25[E1750000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2159                              <1> getc_n:
  2160                              <1> 	; 30/06/2015
  2161 0000651E 08E4                <1> 	or	ah, ah
  2162 00006520 740D                <1> 	jz	short getc0 
  2163 00006522 D0E4                <1> 	shl	ah, 1
  2164 00006524 0FB6DC              <1> 	movzx	ebx, ah
  2165 00006527 81C3[C8700000]      <1> 	add	ebx, ttychr
  2166 0000652D EB05                <1> 	jmp	short getc1
  2167                              <1> getc0:
  2168 0000652F BB[C8700000]        <1> 	mov	ebx, ttychr
  2169                              <1> getc1:
  2170 00006534 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2171                              <1> 				; (by kb_int)	
  2172 00006537 6609C9              <1> 	or	cx, cx
  2173 0000653A 7507                <1> 	jnz	short getc2
  2174 0000653C 20C0                <1> 	and 	al, al
  2175 0000653E 7415                <1> 	jz	short getc_s
  2176                              <1> 	;xor	ax, ax
  2177                              <1> 	; 30/11/2021
  2178 00006540 31C0                <1> 	xor	eax, eax
  2179 00006542 C3                  <1> 	retn
  2180                              <1> getc2:	
  2181 00006543 20C0                <1> 	and	al, al
  2182 00006545 6689C8              <1> 	mov	ax, cx
  2183 00006548 66B90000            <1> 	mov	cx, 0
  2184 0000654C 7506                <1> 	jnz	short getc3
  2185                              <1> getc_sn:
  2186 0000654E 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2187 00006551 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2188                              <1> getc3:
  2189 00006554 C3                  <1> 	retn
  2190                              <1> getc_s:
  2191                              <1> 	; 12/11/2015
  2192                              <1> 	; 15/09/2015
  2193                              <1> 	; 01/07/2015
  2194                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2195                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2196                              <1> 	;
  2197                              <1> 	; tty  of the current process is not 
  2198                              <1> 	; current tty (ptty); so, current process only 
  2199                              <1> 	; can use keyboard input when its tty becomes 
  2200                              <1> 	; current tty (ptty).
  2201                              <1> 	; 'sleep' is for preventing an endless lock
  2202                              <1> 	; during this tty input request.
  2203                              <1> 	; (Because, the user is not looking at the video page
  2204                              <1> 	; of the process to undersand there is a keyboard
  2205                              <1> 	; input request.)
  2206                              <1> 	;
  2207                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2208                              <1> 	;
  2209                              <1> 	; 05/10/2013
  2210                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2211                              <1> 	;
  2212                              <1> 	; 10/10/2013
  2213                              <1> gcw0:
  2214 00006555 B10A                <1> 	mov	cl, 10 ; ch = 0
  2215                              <1> gcw1:	
  2216                              <1> 	; 12/11/2015
  2217 00006557 E8F9D6FFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2218                              <1> 	; 10/10/2013
  2219 0000655C E831EBFFFF          <1> 	call	idle
  2220 00006561 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2221                              <1> 				; (by kb_int)
  2222 00006564 6609C0              <1> 	or	ax, ax
  2223                              <1> ;	jnz	short gcw3
  2224 00006567 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2225                              <1> 	; 30/06/2015
  2226 00006569 FEC9                <1> 	dec	cl
  2227 0000656B 75EA                <1> 	jnz	short gcw1
  2228                              <1> 	;
  2229 0000656D 8A25[E1750000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2230                              <1> ;	; 10/12/2013
  2231                              <1> ;	cmp 	ah, [ptty]
  2232                              <1> ;	jne	short gcw2
  2233                              <1> ;	; 14/02/2014
  2234                              <1> ;	cmp	byte [u.uno], 1
  2235                              <1> ;	jna	short gcw0		
  2236                              <1> ;gcw2:
  2237 00006573 E8A7EBFFFF          <1> 	call	sleep
  2238                              <1> 	;
  2239                              <1> 	; 20/09/2013
  2240 00006578 8A25[E1750000]      <1> 	mov	ah, [u.ttyn]
  2241 0000657E 30C0                <1> 	xor 	al, al
  2242 00006580 EB9C                <1> 	jmp	short getc_n
  2243                              <1> ;gcw3:
  2244                              <1> gcw2: 	; 15/09/2015
  2245                              <1> 	; 10/10/2013
  2246 00006582 30C9                <1> 	xor	cl, cl
  2247 00006584 EBC8                <1> 	jmp	short getc_sn
  2248                              <1> 
  2249                              <1> putc:	
  2250                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2251                              <1> 	; 13/08/2015
  2252                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2253                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2254                              <1> 	;
  2255                              <1> 	; Retro UNIX 8086 v1 modification !
  2256                              <1> 	; 
  2257                              <1> 	; 'putc' puts a character 
  2258                              <1> 	;	 onto requested (tty) video page or
  2259                              <1> 	;	 serial port
  2260                              <1> 	; INPUTS ->
  2261                              <1> 	;     AL = ascii code of the character
  2262                              <1> 	;     AH = video page (tty) number (0 to 7)
  2263                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2264                              <1> 	; OUTPUTS ->
  2265                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2266                              <1> 	;      			ZF=0 -> AX has (current) character
  2267                              <1> 	;     cf=0 and AH = 0 -> no error
  2268                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)
  2269                              <1> 	; 
  2270                              <1> 	; Original UNIX V1 'putc': 
  2271                              <1> 	;     put a character at the end of character list
  2272                              <1> 	;
  2273                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2274                              <1> 	;
  2275 00006586 80FC07              <1> 	cmp	ah, 7
  2276 00006589 770A                <1>         ja      short sndc ; 05/12/2021
  2277                              <1> 	; 30/06/2015
  2278 0000658B 0FB6DC              <1> 	movzx	ebx, ah
  2279                              <1> 	; 13/08/2015
  2280 0000658E B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2281 00006590 E92FAEFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2282                              <1> 
  2283                              <1> sndc:   ; <Send character>
  2284                              <1> 	;
  2285                              <1> 	; 12/01/2022
  2286                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2287                              <1> 	; 17/11/2015
  2288                              <1> 	; 16/11/2015
  2289                              <1> 	; 11/11/2015
  2290                              <1> 	; 10/11/2015
  2291                              <1> 	; 09/11/2015
  2292                              <1> 	; 08/11/2015
  2293                              <1> 	; 07/11/2015
  2294                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2295                              <1> 	; 29/10/2015
  2296                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2297                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2298                              <1> 	;
  2299                              <1> 	; Retro UNIX 8086 v1 feature only !
  2300                              <1> 	;
  2301                              <1> 	; ah = [u.ttyn]
  2302                              <1> 	;
  2303                              <1> 	; 30/06/2015
  2304 00006595 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2305                              <1> 	; 07/11/2015
  2306 00006598 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2307                              <1> sndc0:
  2308                              <1> 	; 07/11/2015
  2309 0000659B E8CDEBFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2310 000065A0 7405                <1> 	jz	short sndc1
  2311 000065A2 E8AED6FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2312                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2313                              <1> sndc1:
  2314                              <1> 	; 16/11/2015
  2315                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2316                              <1> 	; 24/12/2021
  2317 000065A7 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2318                              <1> sndcx:
  2319 000065A9 8A83[0A710000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2320 000065AF 8AA3[08710000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2321                              <1> 	;
  2322                              <1> 	; 17/11/2015
  2323                              <1> 	; check 'request for response' status
  2324 000065B5 80BB[04710000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2325 000065BC 740A                <1> 	jz	short query
  2326                              <1> response:
  2327 000065BE FE05[07710000]      <1> 	inc 	byte [comqr] ; query or response status
  2328 000065C4 B0FF                <1> 	mov	al, 0FFh	 
  2329 000065C6 EB14                <1> 	jmp	short sndc3
  2330                              <1> query:
  2331 000065C8 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2332 000065CA 750E                <1> 	jnz 	short sndc2 ; normal character
  2333                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2334                              <1> 	;je	short sndc2  ; yes, already responded
  2335                              <1> 	; 16/11/2015
  2336                              <1> 	; query: request for response (again)
  2337 000065CC 8883[08710000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2338 000065D2 FE05[07710000]      <1> 	inc 	byte [comqr] ; query or response status
  2339 000065D8 EB02                <1> 	jmp	short sndc3
  2340                              <1> sndc2:
  2341 000065DA 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2342                              <1> sndc3:
  2343 000065DC 8883[0A710000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2344 000065E2 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2345                              <1> 	; 30/06/2015
  2346 000065E4 E88FCFFFFF          <1> 	call	sp_status ; get serial port status
  2347                              <1> 	; AL = Line status, AH = Modem status
  2348                              <1> 	; 07/11/2015
  2349 000065E9 A880                <1> 	test	al, 80h
  2350 000065EB 7504                <1> 	jnz	short sndc4
  2351 000065ED A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2352 000065EF 751A                <1> 	jnz	short sndc5
  2353                              <1> sndc4: 	; Check line status again
  2354                              <1> 	; 16/11/2015
  2355                              <1> 	;push	cx
  2356                              <1> 	; 24/12/2021
  2357 000065F1 51                  <1> 	push	ecx
  2358                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2359                              <1> 	; 12/01/2022
  2360 000065F2 31C9                <1> 	xor	ecx, ecx
  2361 000065F4 B106                <1> 	mov	cl, 6
  2362 000065F6 E8C0AEFFFF          <1> 	call	WAITF
  2363                              <1> 	;pop	cx
  2364                              <1> 	; 24/12/1021
  2365 000065FB 59                  <1> 	pop	ecx
  2366                              <1> 	;
  2367 000065FC 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2368 000065FE E875CFFFFF          <1> 	call	sp_status ; get serial port status
  2369                              <1> 	; 16/11/2015
  2370                              <1> 	; 09/11/2015
  2371                              <1> 	; 08/11/2015
  2372 00006603 A880                <1> 	test	al, 80h	; time out error
  2373 00006605 7565                <1>         jnz     short sndc7
  2374 00006607 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2375 00006609 7461                <1>         jz	short sndc7
  2376                              <1> sndc5:  
  2377 0000660B 8A83[0A710000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2378 00006611 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2379 00006615 28DE                <1> 	sub	dh, bl
  2380 00006617 EE                  <1> 	out	dx, al	   ; send on serial port
  2381                              <1> 	; 10/11/2015
  2382                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2383                              <1> 	; (to improve text flow to the terminal)
  2384                              <1> 	; ('diskette.inc': 'WAITF')
  2385                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2386                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2387                              <1> 	;push	cx
  2388                              <1> 	; 24/12/2021
  2389 00006618 51                  <1> 	push	ecx
  2390                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2391                              <1> 	; 12/01/2022
  2392 00006619 29C9                <1> 	sub	ecx, ecx
  2393 0000661B B106                <1> 	mov	cl, 6
  2394 0000661D E899AEFFFF          <1> 	call	WAITF
  2395                              <1> 	;pop	cx
  2396                              <1> 	; 24/12/1021
  2397 00006622 59                  <1> 	pop	ecx
  2398                              <1>     	;
  2399                              <1> 	; 07/11/2015
  2400 00006623 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2401                              <1> 	;
  2402 00006625 E84ECFFFFF          <1> 	call	sp_status ; get serial port status
  2403                              <1> 	; AL = Line status, AH = Modem status
  2404                              <1> 	;
  2405 0000662A E83EEBFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2406 0000662F 7405                <1> 	jz	short sndc6
  2407 00006631 E81FD6FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2408                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2409                              <1> sndc6:
  2410 00006636 3C80                <1> 	cmp	al, 80h
  2411 00006638 7332                <1> 	jnb	short sndc7		
  2412                              <1> 	;
  2413 0000663A 803D[07710000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2414 00006641 7244                <1> 	jb	short sndc8 	; no, normal character
  2415 00006643 883D[07710000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2416                              <1> 	; 17/11/2015
  2417 00006649 E844EAFFFF          <1> 	call	idle
  2418                              <1> 	;
  2419 0000664E 38BB[0A710000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2420                              <1>         ;ja	sndc2       ; response (will be followed by
  2421                              <1> 			    ; a normal character)
  2422                              <1> 	; 24/12/2021
  2423 00006654 7602                <1> 	jna	short sndc_10
  2424 00006656 EB82                <1> 	jmp	sndc2
  2425                              <1> sndc_10:
  2426                              <1> 	; Query request must be responded by the terminal
  2427                              <1> 	; before sending a normal character !
  2428 00006658 53                  <1> 	push	ebx
  2429                              <1> 	;push	cx ; *** cl = character (to be sent)
  2430                              <1> 	; 24/12/2021
  2431 00006659 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2432 0000665A 8A25[E1750000]      <1> 	mov	ah, [u.ttyn]
  2433 00006660 E8BAEAFFFF          <1> 	call	sleep ; this process will be awakened by
  2434                              <1> 		      ; received data available interrupt
  2435                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2436                              <1> 	; 24/12/2021
  2437 00006665 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2438 00006666 5B                  <1> 	pop	ebx
  2439 00006667 E93DFFFFFF          <1>         jmp	sndcx
  2440                              <1> sndc7:
  2441                              <1> 	 ; 16/11/2015
  2442 0000666C 803D[07710000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2443 00006673 7213                <1> 	jb	short sndc9 	; no
  2444                              <1> 	;
  2445 00006675 88BB[08710000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2446 0000667B 88BB[0A710000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2447                              <1> 	;
  2448 00006681 883D[07710000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2449                              <1> sndc8:
  2450 00006687 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2451                              <1> sndc9:
  2452                              <1> 	; AL = Line status, AH = Modem status
  2453 00006688 C3                  <1> 	retn
  2454                              <1> 
  2455                              <1> get_cpos:
  2456                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2457                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2458                              <1> 	;
  2459                              <1> 	; INPUT -> bl = video page number
  2460                              <1> 	; RETURN -> dx = cursor position
  2461                              <1> 
  2462 00006689 53                  <1> 	push	ebx
  2463 0000668A 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2464 0000668D D0E3                <1> 	shl	bl, 1
  2465 0000668F 81C3[B6700000]      <1> 	add	ebx, cursor_posn
  2466 00006695 668B13              <1> 	mov	dx, [ebx]
  2467 00006698 5B                  <1> 	pop	ebx
  2468 00006699 C3                  <1> 	retn
  2469                              <1> 
  2470                              <1> read_ac_current:
  2471                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2472                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2473                              <1> 	;
  2474                              <1> 	; INPUT -> bl = video page number
  2475                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2476                              <1> 
  2477 0000669A E88FAEFFFF          <1> 	call 	find_position ; 'video.inc'
  2478                              <1> 	; dx = status port
  2479                              <1> 	; esi = cursor location/address
  2480 0000669F 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2481 000066A5 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2482 000066A8 C3                  <1> 	retn
  2483                              <1> 
  2484                              <1> syssleep:
  2485                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2486                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2487                              <1> 	;
  2488                              <1> 	; Retro UNIX 8086 v1 feature only
  2489                              <1> 	; (INPUT -> none)
  2490                              <1> 	;
  2491 000066A9 0FB61D[FD750000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2492 000066B0 8AA3[D7710000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2493 000066B6 E864EAFFFF          <1> 	call	sleep
  2494 000066BB E9A8D4FFFF          <1> 	jmp	sysret
  2495                              <1> 
  2496                              <1> vp_clr:
  2497                              <1> 	; Reset/Clear Video Page
  2498                              <1> 	;
  2499                              <1> 	; 05/12/2021 - (Retro UNIX 386 v1.2)
  2500                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2501                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2502                              <1> 	;
  2503                              <1> 	; Retro UNIX 8086 v1 feature only !
  2504                              <1> 	;
  2505                              <1> 	; INPUTS -> 
  2506                              <1> 	;   BL = video page number	 
  2507                              <1> 	;
  2508                              <1> 	; OUTPUT ->
  2509                              <1> 	;   none
  2510                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2511                              <1> 	;
  2512                              <1> 	; 04/12/2013
  2513 000066C0 28C0                <1> 	sub	al, al
  2514                              <1> 	; al = 0 (clear video page)
  2515                              <1> 	; bl = video page
  2516 000066C2 B407                <1> 	mov	ah, 07h
  2517                              <1> 	; ah = 7 (attribute/color)
  2518                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2519                              <1> 	; 05/12/2021
  2520 000066C4 31C9                <1> 	xor	ecx, ecx
  2521 000066C6 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2522 000066CA E889AEFFFF          <1> 	call	scroll_up
  2523                              <1> 	; bl = video page
  2524                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2525                              <1> 	; 05/12/2021
  2526 000066CF 31D2                <1> 	xor	edx, edx
  2527 000066D1 E9F8ADFFFF          <1> 	jmp 	set_cpos
  2528                              <1> 
  2529                              <1> sysmsg:
  2530                              <1> 	; 11/12/2021
  2531                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2532                              <1> 	; 11/11/2015
  2533                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2534                              <1> 	; Print user-application message on user's console tty
  2535                              <1> 	;
  2536                              <1> 	; Input -> EBX = Message address
  2537                              <1> 	;	   ECX = Message length (max. 255)
  2538                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2539                              <1> 	;
  2540 000066D6 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2541                              <1> 	;ja	sysret ; nothing to do with big message size
  2542 000066DC 7779                <1> 	ja	short sysmsg8 ; 11/12/2021
  2543 000066DE 08C9                <1> 	or	cl, cl
  2544                              <1> 	;jz	sysret
  2545 000066E0 7475                <1> 	jz	short sysmsg8 ; 11/12/2021
  2546 000066E2 20D2                <1> 	and	dl, dl
  2547 000066E4 7502                <1> 	jnz	short sysmsg0
  2548 000066E6 B207                <1> 	mov	dl, 07h ; default color
  2549                              <1> 		; (black background, light gray character)
  2550                              <1> sysmsg0:
  2551 000066E8 891D[D0750000]      <1> 	mov	[u.base], ebx
  2552 000066EE 8815[C7700000]      <1> 	mov	[ccolor], dl ; color attributes
  2553 000066F4 89E5                <1> 	mov	ebp, esp
  2554 000066F6 31DB                <1> 	xor	ebx, ebx ; 0
  2555 000066F8 891D[D8750000]      <1> 	mov	[u.nread], ebx ; 0
  2556                              <1> 	;
  2557 000066FE 381D[1E760000]      <1> 	cmp	[u.kcall], bl ; 0
  2558 00006704 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2559                              <1> 	;
  2560 00006706 890D[D4750000]      <1> 	mov	[u.count], ecx
  2561 0000670C 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ ; 04/12/2021
  2562                              <1> 	; 04/12/2021
  2563                              <1> 	; (dword alignment for esp)
  2564 0000670D F6C103              <1> 	test	cl, 3
  2565 00006710 7404                <1> 	jz	short sysmsg_7
  2566 00006712 80C903              <1> 	or	cl, 3
  2567 00006715 41                  <1> 	inc	ecx
  2568                              <1> sysmsg_7:
  2569 00006716 29CC                <1> 	sub	esp, ecx
  2570 00006718 89E7                <1> 	mov	edi, esp
  2571 0000671A 89E6                <1> 	mov	esi, esp
  2572 0000671C 66891D[18760000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2573                              <1> 	; 11/11/2015 
  2574 00006723 8A25[E2750000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2575                              <1> 	; 0 = none
  2576 00006729 FECC                <1> 	dec	ah
  2577 0000672B 790C                <1> 	jns	short sysmsg1 
  2578 0000672D 8A1D[FD750000]      <1> 	mov	bl, [u.uno] ; process number	
  2579 00006733 8AA3[D7710000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2580                              <1> sysmsg1:
  2581 00006739 8825[E1750000]      <1> 	mov	[u.ttyn], ah
  2582                              <1> sysmsg2:
  2583 0000673F E808F5FFFF          <1> 	call	cpass
  2584 00006744 7416                <1> 	jz	short sysmsg5
  2585 00006746 AA                  <1> 	stosb
  2586 00006747 20C0                <1> 	and	al, al
  2587 00006749 75F4                <1> 	jnz	short sysmsg2
  2588                              <1> sysmsg3:
  2589 0000674B 80FC07              <1> 	cmp	ah, 7 ; tty number
  2590 0000674E 7711                <1> 	ja	short sysmsg6 ; serial port
  2591 00006750 E83E000000          <1> 	call	print_cmsg
  2592                              <1> sysmsg4:
  2593 00006755 89EC                <1> 	mov	esp, ebp
  2594                              <1> sysmsg8: ; 11/12/2021	
  2595 00006757 E90CD4FFFF          <1> 	jmp	sysret
  2596                              <1> sysmsg5:
  2597 0000675C C60700              <1> 	mov	byte [edi], 0
  2598 0000675F EBEA                <1> 	jmp	short sysmsg3
  2599                              <1> sysmsg6:
  2600 00006761 8A06                <1> 	mov	al, [esi]
  2601 00006763 E82DFEFFFF          <1> 	call	sndc
  2602 00006768 72EB                <1> 	jc	short sysmsg4
  2603 0000676A 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2604 0000676D 76E6                <1> 	jna	short sysmsg4
  2605 0000676F 46                  <1> 	inc 	esi
  2606 00006770 8A25[E1750000]      <1> 	mov	ah, [u.ttyn]
  2607 00006776 EBE9                <1> 	jmp	short sysmsg6
  2608                              <1> 
  2609                              <1> sysmsgk: ; Temporary (01/07/2015)
  2610                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2611                              <1> 	; (ECX -character count- will not be considered)
  2612 00006778 8B35[D0750000]      <1> 	mov	esi, [u.base]
  2613 0000677E 8A25[C6700000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2614 00006784 8825[E1750000]      <1> 	mov	[u.ttyn], ah
  2615 0000678A C605[1E760000]00    <1> 	mov	byte [u.kcall], 0
  2616 00006791 EBB8                <1> 	jmp	short sysmsg3
  2617                              <1> 	
  2618                              <1> print_cmsg: 
  2619                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2620                              <1> 	;
  2621                              <1> 	; print message (on user's console tty) 
  2622                              <1> 	;	with requested color
  2623                              <1> 	;
  2624                              <1> 	; INPUTS:
  2625                              <1> 	;	esi = message address
  2626                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2627                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2628                              <1> 	;
  2629 00006793 AC                  <1> 	lodsb
  2630                              <1> pcmsg1:
  2631 00006794 56                  <1> 	push 	esi
  2632 00006795 0FB61D[E1750000]    <1>         movzx   ebx, byte [u.ttyn]
  2633 0000679C 8A25[C7700000]      <1> 	mov	ah, [ccolor]
  2634 000067A2 E81DACFFFF          <1> 	call 	write_tty
  2635 000067A7 5E                  <1> 	pop	esi
  2636 000067A8 AC                  <1> 	lodsb
  2637 000067A9 20C0                <1> 	and 	al, al  ; 0
  2638 000067AB 75E7                <1> 	jnz 	short pcmsg1
  2639 000067AD C3                  <1> 	retn
  2640                              <1> 
  2641                              <1> sysgeterr:
  2642                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.2
  2643                              <1> 	; 09/12/2015
  2644                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2645                              <1> 	; Get last error number or page fault count
  2646                              <1> 	; (for debugging)
  2647                              <1> 	;
  2648                              <1> 	; Input -> EBX = return type
  2649                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2650                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2651                              <1> 	;	   FFFFFFFEh = total page fault count
  2652                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2653                              <1> 	;
  2654                              <1> 	; Output -> EAX = last error number or page fault count
  2655                              <1> 	;	   (depending on EBX input)
  2656                              <1> 	; 	
  2657 000067AE 21DB                <1> 	and 	ebx, ebx
  2658 000067B0 750F                <1> 	jnz	short glerr_2
  2659                              <1> glerr_0:
  2660 000067B2 A1[20760000]        <1> 	mov	eax, [u.error]
  2661                              <1> glerr_1:
  2662 000067B7 A3[AC750000]        <1> 	mov	[u.r0], eax
  2663                              <1> 	;retn
  2664                              <1>  	; 16/02/2022 (BugFix)
  2665 000067BC E9A7D3FFFF          <1> 	jmp	sysret
  2666                              <1> glerr_2:
  2667 000067C1 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2668 000067C2 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2669 000067C4 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2670 000067C5 75EB                <1> 	jnz	short glerr_0
  2671 000067C7 A1[50710000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2672 000067CC EBE9                <1>         jmp     short glerr_1
  2673                              <1> glerr_3:
  2674 000067CE A1[24760000]        <1> 	mov 	eax, [u.pfcount]
  2675 000067D3 EBE2                <1> 	jmp	short glerr_1
  2096                                  
  2097                                  ; 07/03/2015
  2098                                  ; Temporary Code
  2099                                  display_disks:
  2100 000067D5 803D[8E6B0000]00        	cmp 	byte [fd0_type], 0
  2101 000067DC 7605                    	jna 	short ddsks1
  2102 000067DE E87D000000              	call	pdskm
  2103                                  ddsks1:
  2104 000067E3 803D[8F6B0000]00        	cmp	byte [fd1_type], 0
  2105 000067EA 760C                    	jna	short ddsks2
  2106 000067EC C605[7F6D0000]31        	mov	byte [dskx], '1'
  2107 000067F3 E868000000              	call	pdskm
  2108                                  ddsks2:
  2109 000067F8 803D[906B0000]00        	cmp	byte [hd0_type], 0
  2110 000067FF 7654                    	jna	short ddsk6
  2111 00006801 66C705[7D6D0000]68-     	mov	word [dsktype], 'hd'
  2111 00006809 64                 
  2112 0000680A C605[7F6D0000]30        	mov	byte [dskx], '0'
  2113 00006811 E84A000000              	call	pdskm
  2114                                  ddsks3:
  2115 00006816 803D[916B0000]00        	cmp	byte [hd1_type], 0
  2116 0000681D 7636                    	jna	short ddsk6
  2117 0000681F C605[7F6D0000]31        	mov	byte [dskx], '1'
  2118 00006826 E835000000              	call	pdskm
  2119                                  ddsks4:
  2120 0000682B 803D[926B0000]00        	cmp	byte [hd2_type], 0
  2121 00006832 7621                    	jna	short ddsk6
  2122 00006834 C605[7F6D0000]32        	mov	byte [dskx], '2'
  2123 0000683B E820000000              	call	pdskm
  2124                                  ddsks5:
  2125 00006840 803D[936B0000]00        	cmp	byte [hd3_type], 0
  2126 00006847 760C                    	jna	short ddsk6
  2127 00006849 C605[7F6D0000]33        	mov	byte [dskx], '3'
  2128 00006850 E80B000000              	call	pdskm
  2129                                  ddsk6:
  2130 00006855 BE[8E6D0000]            	mov	esi, nextline
  2131 0000685A E806000000              	call	pdskml
  2132                                  pdskm_ok:
  2133 0000685F C3                      	retn
  2134                                  pdskm:
  2135 00006860 BE[7B6D0000]            	mov	esi, dsk_ready_msg
  2136                                  pdskml:	
  2137 00006865 AC                      	lodsb
  2138 00006866 08C0                    	or	al, al
  2139 00006868 74F5                    	jz	short pdskm_ok
  2140 0000686A 56                      	push	esi
  2141 0000686B 31DB                    	xor	ebx, ebx ; 0
  2142                                  			; Video page 0 (bl=0)
  2143 0000686D B407                    	mov	ah, 07h ; Black background, 
  2144                                  			; light gray forecolor
  2145 0000686F E850ABFFFF              	call	write_tty
  2146 00006874 5E                      	pop	esi
  2147 00006875 EBEE                    	jmp	short pdskml
  2148                                  
  2149 00006877 90<rep 9h>              align 16
  2150                                  
  2151                                  gdt:	; Global Descriptor Table
  2152                                  	; (30/07/2015, conforming cs)
  2153                                  	; (26/03/2015)
  2154                                  	; (24/03/2015, tss)
  2155                                  	; (19/03/2015)
  2156                                  	; (29/12/2013)
  2157                                  	;
  2158 00006880 0000000000000000        	dw 0, 0, 0, 0	; NULL descriptor
  2159                                  	; 18/08/2014
  2160                                  			; 08h kernel code segment, base = 00000000h		
  2161 00006888 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2162                                  			; 10h kernel data segment, base = 00000000h	
  2163 00006890 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2164                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2165 00006898 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2166                                  			; 23h user data segment, base address = 400000h ; CORE
  2167 000068A0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2168                                  			; Task State Segment
  2169 000068A8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2170                                  			       ;  no IO permission in ring 3)
  2171                                  gdt_tss0:
  2172 000068AA 0000                    	dw 0 ; TSS base address, bits 0-15 
  2173                                  gdt_tss1:
  2174 000068AC 00                      	db 0 ; TSS base address, bits 16-23 
  2175                                  	      		; 49h	
  2176 000068AD E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2177 000068AE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2178                                  gdt_tss2:
  2179 000068AF 00                      	db 0 ; TSS base address, bits 24-31 
  2180                                  
  2181                                  gdt_end:
  2182                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2183                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2184                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2185                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2186                                  
  2187                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2188                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2189                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2190                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2191                                  		; W= Writeable, A= Accessed
  2192                                  	
  2193                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2194                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2195                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2196                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2197                                  
  2198                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2199                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2200                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2201                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2202                                  	
  2203                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2204                                  
  2205                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2206                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2207                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2208                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2209                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2210                                  		; AVL= Available to programmers	
  2211                                  
  2212                                  gdtd:
  2213 000068B0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2214 000068B2 [80680000]                      dd gdt			; Address of the GDT
  2215                                  
  2216                                  	; 20/08/2014
  2217                                  idtd:
  2218 000068B6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2219 000068B8 [306E0000]                      dd idt			; Address of the IDT
  2220                                  
  2221                                  align 4
  2222                                  	; 21/08/2014
  2223                                  ilist:
  2224                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2225                                  	;
  2226                                  	; Exception list
  2227                                  	; 25/08/2014	
  2228 000068BC [23080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2229 000068C0 [2A080000]              	dd	exc1	
  2230 000068C4 [31080000]              	dd 	exc2	
  2231 000068C8 [38080000]              	dd	exc3	
  2232 000068CC [3C080000]              	dd	exc4	
  2233 000068D0 [40080000]              	dd	exc5	
  2234 000068D4 [44080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2235 000068D8 [48080000]              	dd	exc7	
  2236 000068DC [4C080000]              	dd	exc8	
  2237 000068E0 [50080000]              	dd	exc9	
  2238 000068E4 [54080000]              	dd 	exc10	
  2239 000068E8 [58080000]              	dd	exc11
  2240 000068EC [5C080000]              	dd	exc12
  2241 000068F0 [60080000]              	dd	exc13	; 0Dh, General Protection Fault
  2242 000068F4 [64080000]              	dd 	exc14	; 0Eh, Page Fault
  2243 000068F8 [68080000]              	dd	exc15
  2244 000068FC [6C080000]              	dd	exc16
  2245 00006900 [70080000]              	dd	exc17
  2246 00006904 [74080000]              	dd 	exc18
  2247 00006908 [78080000]              	dd	exc19
  2248 0000690C [7C080000]              	dd 	exc20
  2249 00006910 [80080000]              	dd	exc21
  2250 00006914 [84080000]              	dd	exc22
  2251 00006918 [88080000]              	dd	exc23
  2252 0000691C [8C080000]              	dd 	exc24
  2253 00006920 [90080000]              	dd	exc25
  2254 00006924 [94080000]              	dd	exc26
  2255 00006928 [98080000]              	dd	exc27
  2256 0000692C [9C080000]              	dd 	exc28
  2257 00006930 [A0080000]              	dd	exc29
  2258 00006934 [A4080000]              	dd 	exc30
  2259 00006938 [A8080000]              	dd	exc31
  2260                                  	; Interrupt list
  2261 0000693C [5E060000]              	dd	timer_int	; INT 20h
  2262                                  		;dd	irq0	
  2263 00006940 [620B0000]              	dd	keyb_int	; 27/08/2014
  2264                                  		;dd	irq1
  2265 00006944 [7D070000]              	dd	irq2
  2266                                  		; COM2 int
  2267 00006948 [81070000]              	dd	irq3
  2268                                  		; COM1 int
  2269 0000694C [8C070000]              	dd	irq4
  2270 00006950 [97070000]              	dd	irq5
  2271                                  ;DISKETTE_INT: ;06/02/2015
  2272 00006954 [47250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2273                                  		;dd	irq6
  2274                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2275                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2276 00006958 [130B0000]              	dd	default_irq7	; 25/02/2015
  2277                                  		;dd	irq7
  2278                                  ; Real Time Clock Interrupt
  2279 0000695C [B1090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2280                                  		;dd	irq8	; INT 28h
  2281 00006960 [A7070000]              	dd	irq9
  2282 00006964 [AB070000]              	dd	irq10
  2283 00006968 [AF070000]              	dd	irq11
  2284 0000696C [B3070000]              	dd	irq12
  2285 00006970 [B7070000]              	dd	irq13
  2286                                  ;HDISK_INT1:  ;06/02/2015 	
  2287 00006974 [6D2D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2288                                  		;dd	irq14
  2289                                  ;HDISK_INT2:  ;06/02/2015
  2290 00006978 [902D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2291                                  		;dd	irq15	; INT 2Fh
  2292                                  		; 14/08/2015
  2293 0000697C [443A0000]              	dd	sysent		; INT 30h (system calls)
  2294                                  	
  2295                                  	;dd	ignore_int
  2296 00006980 00000000                	dd	0
  2297                                  
  2298                                  ;;;
  2299                                  ;;; 11/03/2015
  2300                                  %include 'kybdata.s'	; KEYBOARD (BIOS) DATA
  2301                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2302                              <1> ; Last Modification: 11/03/2015
  2303                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2304                              <1> ;
  2305                              <1> ; ///////// KEYBOARD DATA ///////////////
  2306                              <1> 
  2307                              <1> ; 05/12/2014
  2308                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2309                              <1> ; 03/06/86  KEYBOARD BIOS
  2310                              <1> 
  2311                              <1> ;---------------------------------------------------------------------------------
  2312                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2313                              <1> ;---------------------------------------------------------------------------------
  2314                              <1> 
  2315                              <1> ;-----	TABLES FOR ALT CASE ------------
  2316                              <1> ;-----	ALT-INPUT-TABLE 
  2317 00006984 524F50514B          <1> K30:	db	82,79,80,81,75
  2318 00006989 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2319                              <1> ;-----	SUPER-SHIFT-TABLE 
  2320 0000698E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2321 00006994 161718191E1F        <1> 	db	22,23,24,25,30,31
  2322 0000699A 202122232425        <1> 	db	32,33,34,35,36,37
  2323 000069A0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2324 000069A6 3132                <1> 	db	49,50
  2325                              <1> 
  2326                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2327                              <1> ;-----	KEY_TABLE 
  2328 000069A8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2329 000069A9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2330 000069AE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2331                              <1> _K6L    equ     $-_K6
  2332                              <1> 
  2333                              <1> ;-----	MASK_TABLE
  2334 000069B0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2335 000069B1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2336 000069B6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2337                              <1> 
  2338                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2339 000069B8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2340 000069BE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2341 000069C4 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2342 000069CA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2343 000069D0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2344 000069D6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2345 000069DC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2346 000069E2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2347 000069E8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2348 000069EE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2349                              <1> 	;				;----- FUNCTIONS ------		
  2350 000069F2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2351 000069F8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2352 000069FE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2353 00006A04 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2354 00006A0A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2355                              <1> 
  2356                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2357 00006A10 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2357 00006A19 39302D3D0809        <1>
  2358 00006A1F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2358 00006A28 705B5D0DFF61736466- <1>
  2358 00006A31 67686A6B6C3B27      <1>
  2359 00006A38 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2359 00006A41 6D2C2E2FFF2AFF20FF  <1>
  2360                              <1> ;-----	LC TABLE SCAN
  2361 00006A4A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2362 00006A4F 4041424344          <1> 	db	64,65,66,67,68
  2363 00006A54 FFFF                <1> 	db	-1,-1			; NL, SL
  2364                              <1> 
  2365                              <1> ;-----	KEYPAD TABLE
  2366 00006A56 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2367 00006A5C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2368 00006A63 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2369                              <1> 
  2370                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2371 00006A68 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2371 00006A71 28295F2B0800        <1>
  2372 00006A77 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2372 00006A80 507B7D0DFF41534446- <1>
  2372 00006A89 47484A4B4C3A22      <1>
  2373 00006A90 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2373 00006A99 4D3C3E3FFF2AFF20FF  <1>
  2374                              <1> ;-----	UC TABLE SCAN
  2375 00006AA2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2376 00006AA7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2377 00006AAC FFFF                <1> 	db	-1,-1			; NL, SL
  2378                              <1> 
  2379                              <1> ;-----	NUM STATE TABLE
  2380 00006AAE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2380 00006AB7 3233302E            <1>
  2381                              <1> 	;
  2382 00006ABB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2383                              <1> 
  2384                              <1> Align	4
  2385                              <1> ;----------------------------------------
  2386                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2387                              <1> ;----------------------------------------
  2388 00006AC0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2389 00006AC1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2390                              <1> 				; (29h default setting for video mode 3)
  2391                              <1> 				; Mode Select register Bits
  2392                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2393                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2394                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2395                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2396                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2397                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2398                              <1> 				;   BIT 6, 7 - Not Used
  2399                              <1> 
  2400                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2401                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2402                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2403                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2404                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2405                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2406                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2407                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2408                              <1> ; Mode & 37h = Video signal OFF
  2409                              <1> 			
  2410                              <1> 
  2411                              <1> ; 26/08/2014
  2412                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2413                              <1> ; Derived from IBM "pc-at" 
  2414                              <1> ; rombios source code (06/10/1985)
  2415                              <1> ; 'dseg.inc'
  2416                              <1> 
  2417                              <1> ;---------------------------------------;
  2418                              <1> ;	SYSTEM DATA AREA		;
  2419                              <1> ;----------------------------------------
  2420 00006AC2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2421                              <1> 
  2422                              <1> ;----------------------------------------
  2423                              <1> ;	KEYBOARD DATA AREAS		;
  2424                              <1> ;----------------------------------------
  2425                              <1> 
  2426 00006AC3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2427 00006AC4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2428 00006AC5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2429 00006AC6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2430 00006AC7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2431 00006AC8 [D86A0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2432 00006ACC [F86A0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2433 00006AD0 [D86A0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2434 00006AD4 [D86A0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2435                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2436 00006AD8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2437                              <1> 
  2438                              <1> ; /// End Of KEYBOARD DATA ///
  2301                                  %include 'vidata.s'	; VIDEO (BIOS) DATA
  2302                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2303                              <1> ; Last Modification: 11/03/2015
  2304                              <1> ;		    (Data section for 'VIDEO.INC')	
  2305                              <1> ;
  2306                              <1> ; ///////// VIDEO DATA ///////////////
  2307                              <1> 
  2308                              <1> video_params:
  2309                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2310                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2311                              <1> 	; VIDEO MODE 3
  2312 00006AF8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2313 00006AFF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2314 00006B04 00000000            <1> 	db	0,0,0,0
  2315                              <1> 
  2316                              <1> ; /// End Of VIDEO DATA ///
  2302                                  %include 'diskdata.s'	; DISK (BIOS) DATA (initialized)
  2303                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2304                              <1> ; Last Modification: 11/03/2015
  2305                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2306                              <1> ;
  2307                              <1> ; *****************************************************************************
  2308                              <1> 
  2309                              <1> ;----------------------------------------
  2310                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2311                              <1> ;	REFERENCED BY POST & BIOS	:
  2312                              <1> ;----------------------------------------
  2313                              <1> 
  2314 00006B08 [6B6B0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2315                              <1> 
  2316                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2317                              <1> ;----------------------------------------------------------------
  2318                              <1> ; DISK_BASE							:
  2319                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2320                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2321                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2322                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2323                              <1> ;----------------------------------------------------------------
  2324                              <1> 
  2325                              <1> ;DISK_BASE:	
  2326                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2327                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2328                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2329                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2330                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2331                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2332                              <1> ;	DB	01BH		; GAP LENGTH
  2333                              <1> ;	DB	0FFH		; DTL
  2334                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2335                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2336                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2337                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2338                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2339                              <1> 
  2340                              <1> ;----------------------------------------
  2341                              <1> ;	ROM BIOS DATA AREAS		:
  2342                              <1> ;----------------------------------------
  2343                              <1> 
  2344                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2345                              <1> 
  2346                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2347                              <1> 
  2348                              <1> ;----------------------------------------
  2349                              <1> ;	DISKETTE DATA AREAS		:
  2350                              <1> ;----------------------------------------
  2351                              <1> 
  2352                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2353                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2354                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2355                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2356                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2357                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2358                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2359                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2360                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2361                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2362                              <1> 
  2363                              <1> ;----------------------------------------
  2364                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2365                              <1> ;----------------------------------------
  2366                              <1> 
  2367                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2368                              <1> 
  2369                              <1> ;----------------------------------------
  2370                              <1> ;	TIMER DATA AREA 		:
  2371                              <1> ;----------------------------------------
  2372                              <1> 
  2373                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2374                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2375                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2376                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2377                              <1> 
  2378                              <1> ;----------------------------------------
  2379                              <1> ;	ADDITIONAL MEDIA DATA		:
  2380                              <1> ;----------------------------------------
  2381                              <1> 
  2382                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2383                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2384                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2385                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2386                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2387                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2388                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2389                              <1> 
  2390                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2391                              <1> 
  2392                              <1> ;--------------------------------------------------------
  2393                              <1> ;	DRIVE TYPE TABLE				:
  2394                              <1> ;--------------------------------------------------------
  2395                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2396                              <1> DR_TYPE:
  2397 00006B0C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2398                              <1>                 ;DW	MD_TBL1
  2399 00006B0D [2A6B0000]          <1> 		dd	MD_TBL1
  2400 00006B11 82                  <1> 		DB	02+BIT7ON
  2401                              <1> 		;DW	MD_TBL2
  2402 00006B12 [376B0000]          <1>                 dd      MD_TBL2
  2403 00006B16 02                  <1> DR_DEFAULT:	DB	02
  2404                              <1>                 ;DW	MD_TBL3
  2405 00006B17 [446B0000]          <1> 		dd      MD_TBL3
  2406 00006B1B 03                  <1> 		DB	03
  2407                              <1>                 ;DW	MD_TBL4
  2408 00006B1C [516B0000]          <1> 		dd      MD_TBL4
  2409 00006B20 84                  <1> 		DB	04+BIT7ON
  2410                              <1>                 ;DW	MD_TBL5
  2411 00006B21 [5E6B0000]          <1> 		dd      MD_TBL5
  2412 00006B25 04                  <1> 		DB	04
  2413                              <1>                 ;DW	MD_TBL6
  2414 00006B26 [6B6B0000]          <1> 		dd      MD_TBL6
  2415                              <1> DR_TYPE_E       equ $			; END OF TABLE
  2416                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2417                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2418                              <1> ;--------------------------------------------------------
  2419                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2420                              <1> ;--------------------------------------------------------
  2421                              <1> ;--------------------------------------------------------
  2422                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2423                              <1> ;--------------------------------------------------------
  2424                              <1> MD_TBL1:        
  2425 00006B2A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2426 00006B2B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2427 00006B2C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2428 00006B2D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2429 00006B2E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2430 00006B2F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2431 00006B30 FF                  <1> 	DB	0FFH		; DTL
  2432 00006B31 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2433 00006B32 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2434 00006B33 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2435 00006B34 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2436 00006B35 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2437 00006B36 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2438                              <1> ;--------------------------------------------------------
  2439                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2440                              <1> ;--------------------------------------------------------
  2441                              <1> MD_TBL2:        
  2442 00006B37 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2443 00006B38 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2444 00006B39 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2445 00006B3A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2446 00006B3B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2447 00006B3C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2448 00006B3D FF                  <1> 	DB	0FFH		; DTL
  2449 00006B3E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2450 00006B3F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2451 00006B40 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2452 00006B41 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2453 00006B42 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2454 00006B43 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2455                              <1> ;--------------------------------------------------------
  2456                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2457                              <1> ;--------------------------------------------------------
  2458                              <1> MD_TBL3:
  2459 00006B44 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2460 00006B45 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2461 00006B46 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2462 00006B47 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2463 00006B48 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2464 00006B49 1B                  <1> 	DB	01BH		; GAP LENGTH
  2465 00006B4A FF                  <1> 	DB	0FFH		; DTL
  2466 00006B4B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2467 00006B4C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2468 00006B4D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2469 00006B4E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2470 00006B4F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2471 00006B50 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2472                              <1> ;--------------------------------------------------------
  2473                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2474                              <1> ;--------------------------------------------------------
  2475                              <1> MD_TBL4:
  2476 00006B51 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2477 00006B52 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2478 00006B53 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2479 00006B54 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2480 00006B55 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2481 00006B56 2A                  <1> 	DB	02AH		; GAP LENGTH
  2482 00006B57 FF                  <1> 	DB	0FFH		; DTL
  2483 00006B58 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2484 00006B59 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2485 00006B5A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2486 00006B5B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2487 00006B5C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2488 00006B5D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2489                              <1> ;--------------------------------------------------------
  2490                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2491                              <1> ;--------------------------------------------------------
  2492                              <1> MD_TBL5:
  2493 00006B5E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2494 00006B5F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2495 00006B60 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2496 00006B61 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2497 00006B62 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2498 00006B63 2A                  <1> 	DB	02AH		; GAP LENGTH
  2499 00006B64 FF                  <1> 	DB	0FFH		; DTL
  2500 00006B65 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2501 00006B66 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2502 00006B67 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2503 00006B68 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2504 00006B69 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2505 00006B6A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2506                              <1> ;--------------------------------------------------------
  2507                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2508                              <1> ;--------------------------------------------------------
  2509                              <1> MD_TBL6:
  2510 00006B6B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2511 00006B6C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2512 00006B6D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2513 00006B6E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2514 00006B6F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2515 00006B70 1B                  <1> 	DB	01BH		; GAP LENGTH
  2516 00006B71 FF                  <1> 	DB	0FFH		; DTL
  2517 00006B72 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2518 00006B73 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2519 00006B74 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2520 00006B75 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2521 00006B76 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2522 00006B77 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2523                              <1> 
  2524                              <1> 
  2525                              <1> ; << diskette.inc >>
  2526                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2527                              <1> ;
  2528                              <1> ;----------------------------------------
  2529                              <1> ;	ROM BIOS DATA AREAS		:
  2530                              <1> ;----------------------------------------
  2531                              <1> 
  2532                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2533                              <1> 
  2534                              <1> ;----------------------------------------
  2535                              <1> ;	FIXED DISK DATA AREAS		:
  2536                              <1> ;----------------------------------------
  2537                              <1> 
  2538                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2539                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2540                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2541                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2542                              <1> 
  2543                              <1> ;----------------------------------------
  2544                              <1> ;	ADDITIONAL MEDIA DATA		:
  2545                              <1> ;----------------------------------------
  2546                              <1> 
  2547                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2548                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2549                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2550                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2551                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2552                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2553                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2554                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2555                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2556                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2557                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2558                              <1> 
  2559                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2560                              <1> ;
  2561                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2562                              <1> 
  2563                              <1> ERR_TBL:
  2564 00006B78 E0                  <1> 	db	NO_ERR
  2565 00006B79 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2566 00006B7D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2567                              <1> 
  2568                              <1> ; 17/12/2014 (mov ax, [cfd])
  2569                              <1> ; 11/12/2014
  2570 00006B81 00                  <1> cfd:		db	0		; current floppy drive (for GET_PARM)
  2571                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2572 00006B82 01                  <1> pfd:		db	1		; previous floppy drive (for GET_PARM)
  2573                              <1> 					; (initial value of 'pfd 
  2574                              <1> 					; must be different then 'cfd' value
  2575                              <1> 					; to force updating/initializing
  2576                              <1> 					; current drive parameters) 
  2577 00006B83 90                  <1> align 2
  2578                              <1> 
  2579 00006B84 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2580                              <1> 			      ; (170h)
  2581 00006B86 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2582                              <1> 
  2583                              <1> ; 05/01/2015 
  2584 00006B88 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2585                              <1> 
  2586                              <1> ; *****************************************************************************
  2303                                  ;;;
  2304                                  
  2305 00006B89 90                      align 2
  2306                                  
  2307                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2308 00006B8A 00                      boot_drv:    db 0  ; boot drive number (physical)
  2309                                  ; 24/11/2014
  2310 00006B8B 00                      drv:	     db 0 
  2311 00006B8C 00                      last_drv:    db 0  ; last hdd
  2312 00006B8D 00                      hdc:         db 0  ; number of hard disk drives
  2313                                  		     ; (present/detected)
  2314                                  ;
  2315                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2316                                  ; Physical drive type & flags
  2317 00006B8E 00                      fd0_type:    db 0  ; floppy drive type
  2318 00006B8F 00                      fd1_type:    db 0    ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2319                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2320                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2321                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2322                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2323 00006B90 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 - present flag)
  2324 00006B91 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 - present flag)
  2325 00006B92 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 - present flag)
  2326 00006B93 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 - present flag)
  2327                                  		     ; bit 0 - Fixed disk access subset supported
  2328                                  		     ; bit 1 - Drive locking and ejecting
  2329                                  		     ; bit 2 - Enhanced disk drive support
  2330                                  		     ; bit 3 - Reserved (64 bit EDD support)
  2331                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2332                                  		     ; will interpret it as 'LBA ready'!)		
  2333                                  
  2334                                  ; 11/03/2015 - 10/07/2015
  2335 00006B94 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2335 00006B9D 0000000000         
  2336 00006BA2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2336 00006BAB 0000000000         
  2337 00006BB0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2337 00006BB9 0000000000         
  2338 00006BBE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2338 00006BC7 000000000000000000-
  2338 00006BD0 000000000000000000-
  2338 00006BD9 00                 
  2339 00006BDA 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2340 00006BE1 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2341                                  ;
  2342                                  
  2343                                  ; 27/08/2014
  2344                                  scr_row:
  2345 00006BE8 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2346                                  scr_col:
  2347 00006BEC 00000000                	dd 0
  2348                                  
  2349                                  ;; 14/08/2015
  2350                                  ;;msgPM:
  2351                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2352                                  msgKVER:
  2353 00006BF0 526574726F20554E49-     	db "Retro UNIX 386 v1.2 - Kernel v0.2.2.0 [26/03/2022]", 0
  2353 00006BF9 58203338362076312E-
  2353 00006C02 32202D204B65726E65-
  2353 00006C0B 6C2076302E322E322E-
  2353 00006C14 30205B32362F30332F-
  2353 00006C1D 323032325D00       
  2354                                  
  2355 00006C23 90                      align 2
  2356                                  
  2357                                  ; 20/08/2014
  2358                                    ; /* This is the default interrupt "handler" :-) */ 
  2359                                    ; Linux v0.12 (head.s)
  2360                                  int_msg:
  2361 00006C24 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2361 00006C2D 6E7465727275707420-
  2361 00006C36 212000             
  2362                                  
  2363 00006C39 90                      align 2  
  2364                                  
  2365                                  ; 21/08/2014
  2366                                  timer_msg:
  2367 00006C3A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2367 00006C43 542032306829202120-
  2367 00006C4C 54696D657220496E74-
  2367 00006C55 657272757074203A20 
  2368                                  tcountstr:
  2369 00006C5E 303030303020            	db "00000 "
  2370 00006C64 00                      	db 0
  2371                                  
  2372 00006C65 90                      align 2
  2373                                  	; 21/08/2014
  2374                                  exc_msg:
  2375 00006C66 435055206578636570-     	db "CPU exception ! "
  2375 00006C6F 74696F6E202120     
  2376                                  excnstr: 		; 25/08/2014
  2377 00006C76 3F3F68202045495020-     	db "??h", "  EIP : "
  2377 00006C7F 3A20               
  2378                                  EIPstr: ; 29/08/2014
  2379 00006C81 00<rep Ch>              	times 12 db 0
  2380                                  rtc_msg:
  2381 00006C8D 5265616C2054696D65-     	db "Real Time Clock - "
  2381 00006C96 20436C6F636B202D20 
  2382                                  datestr:
  2383 00006C9F 30302F30302F303030-     	db "00/00/0000"
  2383 00006CA8 30                 
  2384 00006CA9 20                      	db " "
  2385                                  daystr:
  2386 00006CAA 44415920                	db "DAY "
  2387                                  timestr:	
  2388 00006CAE 30303A30303A3030                db "00:00:00"
  2389 00006CB6 20                      	db " "
  2390 00006CB7 00                      	db 0 
  2391                                  
  2392                                  daytmp:
  2393                                  	; 28/02/2015
  2394 00006CB8 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2394 00006CC1 4F4E20545545205745-
  2394 00006CCA 442054485520465249-
  2394 00006CD3 2053415420         
  2395                                  
  2396 00006CD8 FF                      ptime_seconds: db 0FFh
  2397                                  
  2398                                  	; 23/02/2015
  2399                                  	; 25/08/2014
  2400                                  ;scounter:
  2401                                  ;	db 5
  2402                                  ;	db 19
  2403                                  
  2404                                  ; 28/11/2021
  2405                                  ;; 05/11/2014
  2406                                  ;msg_out_of_memory:
  2407                                  ;	db 	07h, 0Dh, 0Ah
  2408                                  ;	db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2409                                  ; 	db	0Dh, 0Ah, 0
  2410                                  	;
  2411                                  setup_error_msg:
  2412 00006CD9 0D0A                    	db 0Dh, 0Ah
  2413 00006CDB 4469736B2053657475-     	db 'Disk Setup Error!' 
  2413 00006CE4 70204572726F7221   
  2414 00006CEC 0D0A00                  	db 0Dh, 0Ah,0
  2415                                  
  2416                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2417                                  ;crt_ulc: db 0 ; upper left column (for scroll) 
  2418                                  ;	  db 0 ; upper left row (for scroll)	
  2419                                  
  2420                                  ;crt_lrc: db 79 ; lower right column (for scroll) 
  2421                                  ;	  db 24 ; lower right row (for scroll)
  2422                                  
  2423                                  ; 06/11/2014 (Temporary Data)
  2424                                  ; Memory Information message
  2425                                  ; 14/08/2015
  2426                                  msg_memory_info:
  2427 00006CEF 07                      	db	07h
  2428 00006CF0 0D0A                    	db	0Dh, 0Ah
  2429                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2430 00006CF2 546F74616C206D656D-     	db	"Total memory : "
  2430 00006CFB 6F7279203A20       
  2431                                  mem_total_b_str: ; 10 digits
  2432 00006D01 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2432 00006D0A 302062797465730D0A 
  2433 00006D13 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2433 00006D1C 202020202020202020 
  2434                                  mem_total_p_str: ; 7 digits
  2435 00006D25 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2435 00006D2E 616765730D0A       
  2436 00006D34 0D0A                    	db 	0Dh, 0Ah
  2437 00006D36 46726565206D656D6F-     	db	"Free memory  : "
  2437 00006D3F 727920203A20       
  2438                                  free_mem_b_str:  ; 10 digits
  2439 00006D45 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2439 00006D4E 3F2062797465730D0A 
  2440 00006D57 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2440 00006D60 202020202020202020 
  2441                                  free_mem_p_str:  ; 7 digits
  2442 00006D69 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2442 00006D72 616765730D0A       
  2443 00006D78 0D0A00                  	db	0Dh, 0Ah, 0
  2444                                  
  2445                                  dsk_ready_msg:
  2446 00006D7B 0D0A                    	db 	0Dh, 0Ah
  2447                                  dsktype:
  2448 00006D7D 6664                    	db	'fd'
  2449                                  dskx:
  2450 00006D7F 30                      	db	'0'
  2451 00006D80 20                      	db	20h
  2452 00006D81 697320524541445920-     	db 	'is READY ...'
  2452 00006D8A 2E2E2E             
  2453 00006D8D 00                      	db 	0
  2454                                  nextline:
  2455 00006D8E 0D0A00                  	db 	0Dh, 0Ah, 0
  2456                                  
  2457                                  ; KERNEL - SYSINIT Messages
  2458                                  ; 24/08/2015
  2459                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2460                                  ; 14/07/2013
  2461                                  ;kernel_init_err_msg:
  2462                                  ;	db 0Dh, 0Ah
  2463                                  ;	db 07h
  2464                                  ;	db 'Kernel initialization ERROR !'
  2465                                  ;	db 0Dh, 0Ah, 0 
  2466                                  ; 24/08/2015
  2467                                  ;;; (temporary kernel init message has been removed
  2468                                  ;;;  from 'sys_init' code)
  2469                                  ;kernel_init_ok_msg: 
  2470                                  ;	db 0Dh, 0Ah
  2471                                  ;	db 07h
  2472                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2473                                  ;	db 0Dh, 0Ah
  2474                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2475                                  ;	db 0Dh, 0Ah, 0
  2476                                  panic_msg:
  2477 00006D91 0D0A07                  	db 0Dh, 0Ah, 07h
  2478 00006D94 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2478 00006D9D 726E656C2050616E69-
  2478 00006DA6 632021             
  2479 00006DA9 0D0A00                  	db 0Dh, 0Ah, 0
  2480                                  etc_init_err_msg:
  2481 00006DAC 0D0A                    	db 0Dh, 0Ah
  2482 00006DAE 07                      	db 07h
  2483 00006DAF 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2483 00006DB8 74632F696E69742021-
  2483 00006DC1 3F                 
  2484 00006DC2 0D0A00                  	db 0Dh, 0Ah, 0
  2485                                  
  2486                                  ; 10/05/2015
  2487                                  badsys_msg:
  2488 00006DC5 0D0A                    	db 0Dh, 0Ah
  2489 00006DC7 07                      	db 07h
  2490 00006DC8 496E76616C69642053-     	db 'Invalid System Call !'
  2490 00006DD1 797374656D2043616C-
  2490 00006DDA 6C2021             
  2491 00006DDD 0D0A                    	db 0Dh, 0Ah
  2492 00006DDF 4541583A20              	db 'EAX: '
  2493                                  bsys_msg_eax:
  2494 00006DE4 303030303030303068      	db '00000000h'
  2495 00006DED 0D0A                    	db 0Dh, 0Ah
  2496 00006DEF 4549503A20              	db 'EIP: '
  2497                                  bsys_msg_eip:
  2498 00006DF4 303030303030303068      	db '00000000h' 
  2499 00006DFD 0D0A00                  	db 0Dh, 0Ah, 0
  2500                                  
  2501                                  BSYS_M_SIZE equ $ - badsys_msg
  2502                                  
  2503                                  align 2
  2504                                  
  2505                                  ; EPOCH Variables
  2506                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2507                                  ; 09/04/2013 epoch variables
  2508                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2509                                  ;
  2510 00006E00 B207                    year: 	dw 1970
  2511 00006E02 0100                    month: 	dw 1
  2512 00006E04 0100                    day: 	dw 1
  2513 00006E06 0000                    hour: 	dw 0
  2514 00006E08 0000                    minute: dw 0
  2515 00006E0A 0000                    second: dw 0
  2516                                  
  2517                                  DMonth:
  2518 00006E0C 0000                    	dw 0
  2519 00006E0E 1F00                    	dw 31
  2520 00006E10 3B00                    	dw 59
  2521 00006E12 5A00                    	dw 90
  2522 00006E14 7800                    	dw 120
  2523 00006E16 9700                    	dw 151
  2524 00006E18 B500                    	dw 181
  2525 00006E1A D400                    	dw 212
  2526 00006E1C F300                    	dw 243
  2527 00006E1E 1101                    	dw 273
  2528 00006E20 3001                    	dw 304
  2529 00006E22 4E01                    	dw 334
  2530                                  
  2531                                  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2532                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2533 00006E24 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2534                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2535 00006E26 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2536 00006E28 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2537                                  		   ;   between 16 MB and 4 GB.
  2538 00006E2A 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2539                                  
  2540                                  ; 01/01/2022
  2541                                  KEND:
  2542                                  
  2543 00006E2C 90<rep 4h>              align 16
  2544                                  
  2545                                  bss_start:
  2546                                  
  2547                                  ABSOLUTE bss_start
  2548                                  
  2549                                  	; 11/03/2015
  2550                                  	; Interrupt Descriptor Table (20/08/2014)
  2551                                  idt:
  2552 00006E30 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2553                                  idt_end:
  2554                                  
  2555                                  ;alignb 4
  2556                                  
  2557                                  task_state_segment:
  2558                                  	; 24/03/2015
  2559 00007030 ????                    tss.link:   resw 1
  2560 00007032 ????                    	    resw 1
  2561                                  ; tss offset 4	
  2562 00007034 ????????                tss.esp0:   resd 1
  2563 00007038 ????                    tss.ss0:    resw 1
  2564 0000703A ????                    	    resw 1	
  2565 0000703C ????????                tss.esp1:   resd 1
  2566 00007040 ????                    tss.ss1:    resw 1
  2567 00007042 ????                    	    resw 1 	
  2568 00007044 ????????                tss.esp2:   resd 1
  2569 00007048 ????                    tss.ss2:    resw 1
  2570 0000704A ????                    	    resw 1
  2571                                  ; tss offset 28
  2572 0000704C ????????                tss.CR3:    resd 1
  2573 00007050 ????????                tss.eip:    resd 1
  2574 00007054 ????????                tss.eflags: resd 1
  2575                                  ; tss offset 40
  2576 00007058 ????????                tss.eax:    resd 1		 		
  2577 0000705C ????????                tss.ecx:    resd 1
  2578 00007060 ????????                tss.edx:    resd 1
  2579 00007064 ????????                tss.ebx:    resd 1
  2580 00007068 ????????                tss.esp:    resd 1
  2581 0000706C ????????                tss.ebp:    resd 1
  2582 00007070 ????????                tss.esi:    resd 1
  2583 00007074 ????????                tss.edi:    resd 1
  2584                                  ; tss offset 72
  2585 00007078 ????                    tss.ES:     resw 1
  2586 0000707A ????                    	    resw 1	
  2587 0000707C ????                    tss.CS:	    resw 1
  2588 0000707E ????                    	    resw 1
  2589 00007080 ????                    tss.SS:	    resw 1
  2590 00007082 ????                    	    resw 1
  2591 00007084 ????                    tss.DS:	    resw 1
  2592 00007086 ????                    	    resw 1
  2593 00007088 ????                    tss.FS:	    resw 1
  2594 0000708A ????                    	    resw 1
  2595 0000708C ????                    tss.GS:	    resw 1
  2596 0000708E ????                    	    resw 1		
  2597 00007090 ????                    tss.LDTR:   resw 1
  2598 00007092 ????                    	    resw 1
  2599                                  ; tss offset 100		
  2600 00007094 ????                    	    resw 1		
  2601 00007096 ????                    tss.IOPB:   resw 1
  2602                                  ; tss offset 104 
  2603                                  tss_end:
  2604                                  
  2605 00007098 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2606                                  		    ;  (Physical address = Virtual address)	 	
  2607 0000709C ????????                memory_size: resd 1 ; memory size in pages
  2608 000070A0 ????????                free_pages:  resd 1 ; number of free pages		
  2609 000070A4 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2610                                  		    ;   first free page search
  2611 000070A8 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2612                                  		    ;   next free page search will be
  2613                                  		    ;   stopped after it. (end of M.A.T.)
  2614 000070AC ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2615                                  		    ; first free page search
  2616                                  		    ;   will be started on it. (for user)
  2617 000070B0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2618                                  
  2619                                  ;;;
  2620                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2621                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2622 000070B4 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2623                                  			  ; NOTE: active page only
  2624 000070B6 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2625                                  active_page: 
  2626 000070C6 ??                      ptty: 	     resb 1 	  ; current tty
  2627                                  ; 01/07/2015
  2628 000070C7 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2629                                  ; 26/10/2015
  2630                                  ; 07/09/2014
  2631 000070C8 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2632                                  
  2633                                  ; 21/08/2014
  2634 000070DC ????????                tcount:	     resd 1
  2635                                  
  2636                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2637 000070E0 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2638                                  
  2639                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2640                                  ; (open mode locks for pseudo TTYs)
  2641                                  ; [ major tty locks (return error in any conflicts) ]
  2642 000070E4 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2643                                  
  2644                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2645                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2646 000070F8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2647                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2648                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2649                                  ;; 0 means serial port is not available 
  2650                                  ;;comprm: ; 25/06/2014
  2651 00007102 ??                      com1p:       resb 1  ;;0E3h
  2652 00007103 ??                      com2p:       resb 1  ;;0E3h
  2653                                  
  2654                                  ; 17/11/2015
  2655                                  ; request for response (from the terminal)	
  2656 00007104 ????                    req_resp:    resw 1 			
  2657                                  ; 07/11/2015
  2658 00007106 ??                      ccomport:    resb 1 ; current COM (serial) port
  2659                                  		    ; (0= COM1, 1= COM2)
  2660                                  ; 09/11/2015
  2661 00007107 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2662                                  ; 07/11/2015
  2663 00007108 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2664 0000710A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2665                                  
  2666                                  ; 23/10/2015
  2667                                  ; SERIAL PORTS - COMMUNICATION MODES
  2668                                  ; (Retro UNIX 386 v1 feature only!)
  2669                                  ; 0 - command mode (default/initial mode)
  2670                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2671                                  ;;; communication modes for future versions:  
  2672                                  ; // 2 - keyboard mode (ascii+scancode input)
  2673                                  ; // 3 - mouse mode
  2674                                  ; // 4 - device control (output) mode
  2675                                  ; VALID COMMANDS for current version:
  2676                                  ; 	'LOGIN'
  2677                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2678                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2679                                  ;  Login response: db 0FFh, 'login', 0
  2680                                  ;	 ("login request accepted, wait for login prompt") 
  2681                                  ; When a login requests is received and acknowledged (by
  2682                                  ; serial port interrupt handler (communication procedure),
  2683                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2684                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2685                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2686                                  ; 
  2687                                  ; 'sys connect' system call is used to change communication mode
  2688                                  ; except 'LOGIN' command which is used to start terminal mode
  2689                                  ; by using (COM port) terminal.
  2690                                  
  2691                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2692                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2693                                  ;com1mode:    resb 1 ; communication mode for COM1
  2694                                  ;com1com:     resb 1 ; communication command for COM1
  2695                                  ;com2mode:    resb 1 ; communication mode for COM1
  2696                                  ;com2com      resb 1 ; communication command for COM1
  2697                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2698                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2699                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2700                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2701                                  
  2702                                  ; 22/08/2014 (RTC)
  2703                                  ; (Packed BCD)
  2704 0000710C ??                      time_seconds: resb 1
  2705 0000710D ??                      time_minutes: resb 1
  2706 0000710E ??                      time_hours:   resb 1
  2707 0000710F ??                      date_wday:    resb 1
  2708 00007110 ??                      date_day:     resb 1
  2709 00007111 ??                      date_month:   resb 1			
  2710 00007112 ??                      date_year:    resb 1
  2711 00007113 ??                      date_century: resb 1
  2712                                  
  2713                                  %include 'diskbss.s' ; UNINITIALIZED DISK (BIOS) DATA
  2714                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2715                              <1> ; Last Modification: 10/07/2015
  2716                              <1> ;	(Unitialized Disk Parameters Data section for 'DISKIO.INC') 
  2717                              <1> ;
  2718                              <1> ; *****************************************************************************
  2719                              <1> 
  2720                              <1> alignb 2
  2721                              <1> 
  2722                              <1> ;----------------------------------------
  2723                              <1> ;	TIMER DATA AREA 		:
  2724                              <1> ;----------------------------------------
  2725                              <1> 
  2726                              <1> TIMER_LH:	; 16/02/2015
  2727 00007114 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2728 00007116 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2729 00007118 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2730                              <1> 
  2731                              <1> ;----------------------------------------
  2732                              <1> ;	DISKETTE DATA AREAS		:
  2733                              <1> ;----------------------------------------
  2734                              <1> 
  2735 00007119 ??                  <1> SEEK_STATUS:	resb	1
  2736 0000711A ??                  <1> MOTOR_STATUS:	resb	1
  2737 0000711B ??                  <1> MOTOR_COUNT:	resb	1
  2738 0000711C ??                  <1> DSKETTE_STATUS:	resb	1
  2739 0000711D ??????????????      <1> NEC_STATUS:	resb	7
  2740                              <1> 
  2741                              <1> ;----------------------------------------
  2742                              <1> ;	ADDITIONAL MEDIA DATA		:
  2743                              <1> ;----------------------------------------
  2744                              <1> 
  2745 00007124 ??                  <1> LASTRATE:	resb 	1
  2746 00007125 ??                  <1> HF_STATUS:	resb 	1
  2747 00007126 ??                  <1> HF_ERROR:	resb 	1
  2748 00007127 ??                  <1> HF_INT_FLAG:	resb 	1
  2749 00007128 ??                  <1> HF_CNTRL:	resb 	1
  2750 00007129 ????????            <1> DSK_STATE:	resb 	4
  2751 0000712D ????                <1> DSK_TRK:	resb 	2
  2752                              <1> 
  2753                              <1> ;----------------------------------------
  2754                              <1> ;	FIXED DISK DATA AREAS		:
  2755                              <1> ;----------------------------------------
  2756                              <1> 
  2757 0000712F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2758 00007130 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2759 00007131 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2760                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2761                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2762                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2763                              <1> 
  2764 00007132 ????                <1> alignb 4
  2765                              <1> 
  2766                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2767                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2768                              <1> HF_TBL_VEC: ; 22/12/2014	
  2769 00007134 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2770 00007138 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2771 0000713C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2772 00007140 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2773                              <1> 
  2774                              <1> ; 03/01/2015
  2775 00007144 ??                  <1> LBAMode:     	resb	1
  2776                              <1> 
  2777                              <1> ; *****************************************************************************
  2714                                  
  2715                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2716                                  
  2717                                  ;alignb 2
  2718                                  
  2719                                  ; 02/01/2022
  2720                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2721                                  
  2722                                  ; 17/04/2021
  2723                                  ; (memory page swap parameters are disabled as temporary)
  2724                                  ;
  2725                                  ;; Memory (swap) Data (11/03/2015)
  2726                                  ; 09/03/2015
  2727                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2728                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2729                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2730                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2731                                  ;swpd_next:  resd 1 ; next free page block
  2732                                  ;swpd_last:  resd 1 ; last swap page block	
  2733                                  
  2734 00007145 ??????                  alignb 4
  2735                                  
  2736                                  ; 10/07/2015
  2737                                  ; 28/08/2014
  2738 00007148 ????????                error_code:  resd 1
  2739                                  ; 29/08/2014
  2740 0000714C ????????                FaultOffset: resd 1
  2741                                  ; 21/09/2015
  2742 00007150 ????????                PF_Count:    resd 1 ; total page fault count
  2743                                  		    ; (for debugging - page fault analyze)
  2744                                  		    ; 'page _fault_handler' (memory.s)
  2745                                  		    ; 'sysgeterr' (u9.s)
  2746                                  ; 23/02/2022
  2747 00007154 ????????                rtc_ticks:  resd 1  ; (temporary! this rtc counter value may be used 
  2748                                  		    ;  for a system call in next retro unix 386 version)
  2749                                  		    ; -2 ticks per second-
  2750                                  ;; 21/08/2015
  2751                                  ;;buffer: resb (nbuf*520) ;; sysdefs.s, ux.s
  2752                                  
  2753                                  ; 02/01/2022
  2754                                  %include 'ux.s'	; 12/04/2015 (unix system/user/process data)
  2755                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2756                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2757                              <1> ; ****************************************************************************
  2758                              <1> ; Retro UNIX 386 v1.2 Kernel - ux.s
  2759                              <1> ; Last Modification: 21/03/2022
  2760                              <1> ;
  2761                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2762                              <1> ; (Modified from 
  2763                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2764                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2765                              <1> ; ----------------------------------------------------------------------------
  2766                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2767                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2768                              <1> ; <Bell Laboratories (17/3/1972)>
  2769                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2770                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2771                              <1> ; ****************************************************************************
  2772                              <1> 
  2773                              <1> ; 27/02/2022
  2774                              <1> ; 12/01/2022
  2775                              <1> ; 22/11/2021 (Modification in Runix v1.1 'ux.s' for runix v2 fs compatibility)
  2776                              <1> ; 18/07/2021
  2777                              <1> ; 15/07/2021
  2778                              <1> ; 12/05/2021
  2779                              <1> ; 09/05/2021
  2780                              <1> ; 06/05/2021
  2781                              <1> ; 02/05/2021
  2782                              <1> ; 26/01/2020 (NASM version of SuperBlock structure in UNIXHDCP.ASM)
  2783                              <1> 
  2784                              <1> ; 21/12/2019 (UNIXCOPY.COM, UNIXCOPY.ASM, UNIXHDCP.COM, UNIXHDCP.ASM)
  2785                              <1> ; 19/12/2019 (UNIXHDFS.COM, RUFSHDI.ASM)
  2786                              <1> ; 01/09/2019 - Retro UNIX 386 v2 SuperBlock
  2787                              <1> 
  2788                              <1> ; 14/01/2020 - Super Block modification:
  2789                              <1> ;	     - Extended sections/divisions (consequental sectors)
  2790                              <1> ;	     - (for swapping, configuration, boot space etc.)	
  2791                              <1> 
  2792                              <1> ; 26/01/2020 (unix386.s, ux.s)
  2793                              <1> ; 14/01/2020
  2794                              <1> SB.HiddenSects	equ SB.BootSectAddr
  2795                              <1> SB.TotalSects	equ SB.VolumeSize
  2796                              <1> 
  2797                              <1> ; 11/05/2021 (Retro UNIX 386 v2)
  2798                              <1> ; Super block status byte (byte 0 of SB.status dword)
  2799                              <1> ; 	bit 0 - superblock modified flag
  2800                              <1> ; 	bit 1 - inode map modified flag
  2801                              <1> ; 	bit 2 - free blocks map modified flag
  2802                              <1> ; 	bit 3 - inode table modified flag
  2803                              <1> ;; 	bit 4 - boot sector modified flag ; 17/08/2021
  2804                              <1> ; 17/08/2021
  2805                              <1> ;	bit 4 - file data write error (for SB.LastInode)
  2806                              <1> ;	bit 5 - inode table write error (for SB.LastInode)
  2807                              <1> ;	bit 6 - inode map write error (for SB.LastInode)
  2808                              <1> ;	bit 7 - free blocks map write error (for SB.LastInode)
  2809                              <1> 	
  2810                              <1> ; 21/12/2019
  2811                              <1> ; 19/12/2019 - Retro UNIX 386 v2 HD (071h) partition boot sector 
  2812                              <1> ;	       (UNIXHDFS.ASM)
  2813                              <1> ; 04/12/2015 (14 byte file names - Retro UNIX 386 v1.1)
  2814                              <1> ; 14/07/2015 (8 byte file names - Retro UNIX 8086 v1 & Retro UNIX 386 v1.0)
  2815                              <1> 
  2816                              <1> bsFSystemID 	equ 2  ; db 'RUFS'	
  2817                              <1> bsVolumeSerial 	equ 6  ; dd 0 ; (4 bytes)
  2818                              <1> bsFDSign	equ 10 ; db 'fd'
  2819                              <1> bsDriveNumber 	equ 12 ; db 0 ; fd0 or fd1 (0 or 1)
  2820                              <1> bsReserved 	equ 13 ; db 0 ; (512 bytes per sector)	
  2821                              <1> bsSecPerTrack	equ 14 ; db 18 ; (9 or 15)	
  2822                              <1> bsHeads		equ 15 ; db  ; 2
  2823                              <1> bsTracks	equ 16 ; dw 80 ; bsCylinders
  2824                              <1> bs_bf_inode_number equ 18 ; dw 0 ; 0 or Boot/Startup File I-Number
  2825                              <1> bsInfoEndsign	equ 20 ; db '@'
  2826                              <1> ; 21/12/2019
  2827                              <1> bsMagic		equ 20 ; db '@'
  2828                              <1> bsPartitionID	equ 21 ; db 0 ; db 71h
  2829                              <1> bsHiddenSects	equ 22 ; dd 0 ; Hidden sectors (Boot Sector LBA)
  2830                              <1> 
  2831                              <1> ; 22/11/2021 - Retro UNIX v2 I-node Flags
  2832                              <1> ; ------------------------------------------------------------------
  2833                              <1> ; UINSTALL.ASM (included in UNIXFDFS.ASM) - 23/01/2020
  2834                              <1> ; ------------------------------------------------------------------
  2835                              <1> 
  2836                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  2837                              <1> ; 1000000000000000b 	IFREG - 1 = regular file (8000h)
  2838                              <1> ; 0100000000000000b	IFDIR - 1 = directory (4000h)
  2839                              <1> ; 0010000000000000b	IRSVD - 0 = reserved bit (2000h) ; Mounted flag
  2840                              <1> ; 0001000000000000b	ILARG - large file addressing bit (1000h)
  2841                              <1> ; 0000100000000000b	ISUID - set user id on exec (800h)
  2842                              <1> ; 0000010000000000b	ISGID - set group id on exec (400h)
  2843                              <1> ; 0000001000000000b	IEXTT - 1 = use extents (200h)
  2844                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2845                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2846                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2847                              <1> ; 0000000000100000b	read, group (20h)
  2848                              <1> ; 0000000000010000b	write, group (10h)
  2849                              <1> ; 0000000000001000b	execute, group (08h)
  2850                              <1> ; 0000000000000100b	read, others (04h)
  2851                              <1> ; 0000000000000010b	write, others (02h)
  2852                              <1> ; 0000000000000001b	execute, others (01h)
  2853                              <1> 
  2854                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  2855                              <1> ; 1000000000000000b 	IFREG - 0 = device file (8000h)
  2856                              <1> ; 0100000000000000b	IFBLK - 1 = block device (4000h)
  2857                              <1> ; 0010000000000000b	IFCHR - character special (2000h) -always 1-
  2858                              <1> ; 0001000000000000b	IFIFO - fifo special (1000h)
  2859                              <1> ; 0000100000000000b	IPIPE - pipe special (800h) ; 07/02/2020
  2860                              <1> ; 0000010000000000b	IREDIR - redirected (400h)  ; 07/02/2020
  2861                              <1> ; 0000001000000000b	IEXTR - 1 = external device driver (200h)
  2862                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2863                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2864                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2865                              <1> ; 0000000000100000b	read, group (20h)
  2866                              <1> ; 0000000000010000b	write, group (10h)
  2867                              <1> ; 0000000000001000b	execute, group (08h)
  2868                              <1> ; 0000000000000100b	read, others (04h)
  2869                              <1> ; 0000000000000010b	write, others (02h)
  2870                              <1> ; 0000000000000001b	execute, others (01h)
  2871                              <1> 
  2872                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2873                              <1> ; (SB structure has been moved from here to 'sysdefs.s'
  2874                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2875                              <1> ; (('ux.s' bss section addresses are being overlapped
  2876                              <1> ;    when SB structure is defined in 'ux.s'))
  2877                              <1> 
  2878                              <1> %if 0
  2879                              <1> 
  2880                              <1> struc SB ; SuperBlock
  2881                              <1> 
  2882                              <1> .Header:	resd 1
  2883                              <1> ;.HiddenSects:
  2884                              <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2885                              <1> ;.TotalSects:
  2886                              <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)
  2887                              <1> .Version:	resd 1	
  2888                              <1> .BlockSize:	resd 1	
  2889                              <1> .InodeCount:	resd 1	
  2890                              <1> .FreeMapAddr:	resd 1	
  2891                              <1> .FreeMapSize:	resd 1	
  2892                              <1> .InodeMapAddr:	resd 1	
  2893                              <1> .InodeMapSize:	resd 1	
  2894                              <1> .InodeTblAddr:	resd 1	
  2895                              <1> .InodeTblSize:	resd 1	
  2896                              <1> .FreeInodes:	resd 1	
  2897                              <1> .FirstFreeIno:	resd 1	
  2898                              <1> .FreeBlocks:	resd 1	
  2899                              <1> .FirstFreeBlk:	resd 1	
  2900                              <1> .BootSecParms:	resb 19	; v1
  2901                              <1> .BSExtension:	resb 5	; v2 HDFS
  2902                              <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2903                              <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2904                              <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2905                              <1> .ModifTime:	resd 1	; (last) modification time (*)
  2906                              <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2907                              <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2908                              <1> .LBA_rw:	resb 1
  2909                              <1> .ClusterSize:	resb 1
  2910                              <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2911                              <1> .Mounted:	resb 1
  2912                              <1> .MountInode:	resd 1  ; double word
  2913                              <1> .DevMajor:	resb 1
  2914                              <1> .DevMinor:	resb 1
  2915                              <1> .LongName:	resb 1
  2916                              <1> .Direntry32:	resb 1
  2917                              <1> ; 18/07/2021
  2918                              <1> .FileBuffer:	resd 1
  2919                              <1> .ItabBuffer:	resd 1
  2920                              <1> .ImapBuffer:	resd 1
  2921                              <1> .FmapBuffer:	resd 1
  2922                              <1>  ; 15/07/2021
  2923                              <1> .LastInode:	resd 1
  2924                              <1> ; 02/05/2021
  2925                              <1> .FmapIndex:	resd 1
  2926                              <1> .ImapIndex:	resd 1
  2927                              <1> .ItableIndex:	resd 1
  2928                              <1> .Reserved:	resb 508-148 ; 18/07/2021
  2929                              <1> .Footer:	resd 1
  2930                              <1> 
  2931                              <1> endstruc
  2932                              <1> 
  2933                              <1> %endif
  2934                              <1> 
  2935                              <1> alignb 2
  2936                              <1> 
  2937                              <1> inode:
  2938                              <1> 	;; 11/03/2013. 
  2939                              <1> 	;;Derived from UNIX v1 source code 'inode' structure (ux).
  2940                              <1> 	;;i.
  2941                              <1> 	;
  2942                              <1> 	;i.flgs: resw 1
  2943                              <1> 	;i.nlks: resb 1
  2944                              <1> 	;i.uid:	 resb 1
  2945                              <1>         ;i.size: resw 1 ; size
  2946                              <1> 	;i.dskp: resw 8 ; 16 bytes
  2947                              <1> 	;i.ctim: resd 1
  2948                              <1> 	;i.mtim: resd 1
  2949                              <1> 	;i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1)
  2950                              <1> 
  2951                              <1> 	; 26/01/2020
  2952                              <1> 	; Retro UNIX 386 v2.0 - Modified UNIX v7 inode model
  2953                              <1> 	;	(15/09/2029 .. 18/12/2019)
  2954                              <1> 
  2955 00007158 ????                <1> 	i.flgs:   resw 1	; /* mode and type of file */
  2956 0000715A ????                <1> 	i.nlks:	  resw 1	; /* number of links to file */
  2957 0000715C ????                <1> 	i.uid:	  resw 1	; /* owner's user id */  - 0 to 655535 -
  2958 0000715E ??                  <1> 	i.gid:	  resb 1	; /* owner's group id */ - o to 255 -
  2959 0000715F ??                  <1> 	i.size_h: resb 1	; /* number of bytes in file */ ; byte 5
  2960 00007160 ????????            <1> 	i.size:	  resd 1 ; size	; /* number of bytes in file */
  2961 00007164 <res 28h>           <1> 	i.dskp:	  resd 10 ; 40 bytes ; /* disk block addresses */
  2962 0000718C ????????            <1> 	i.atim:	  resd 1	; /* time last accessed */
  2963 00007190 ????????            <1> 	i.mtim:	  resd 1	; /* time last modified */
  2964 00007194 ????????            <1> 	i.ctim:	  resd 1	; /* time created */
  2965                              <1> 
  2966                              <1> I_SIZE	equ $ - inode
  2967                              <1> 
  2968                              <1> process:
  2969                              <1> 	; 27/02/2022
  2970                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2) 
  2971                              <1> 	; 06/05/2015
  2972                              <1> 	; 11/03/2013 - 05/02/2014
  2973                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2974                              <1> 	;p.
  2975                              <1> 	
  2976 00007198 <res 20h>           <1>         p.pid:   resw nproc
  2977 000071B8 <res 20h>           <1>         p.ppid:  resw nproc
  2978                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2979 000071D8 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2980                              <1> 	; 27/02/2022 (p.waitc is not used)
  2981                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2982 000071E8 <res 10h>           <1> 	p.link:	 resb nproc
  2983 000071F8 <res 10h>           <1> 	p.stat:	 resb nproc
  2984                              <1> 
  2985                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 feature only !) 
  2986 00007208 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2987                              <1> 			    ; 'user' structure	
  2988                              <1> 
  2989                              <1> P_SIZE	equ $ - process
  2990                              <1> 
  2991                              <1> ; fsp table (original UNIX v1)
  2992                              <1> ;
  2993                              <1> ;Entry
  2994                              <1> ;          15                                      0
  2995                              <1> ;  1     |---|---------------------------------------|
  2996                              <1> ;        |r/w|       i-number of open file           |
  2997                              <1> ;        |---|---------------------------------------| 
  2998                              <1> ;        |               device number               |
  2999                              <1> ;        |-------------------------------------------|
  3000                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  3001                              <1> ;        |-------------------------------------------| 
  3002                              <1> ;        |  flag that says    | number of processes  |
  3003                              <1> ;        |   file deleted     | that have file open  |
  3004                              <1> ;        |-------------------------------------------| 
  3005                              <1> ;  2     |                                           |
  3006                              <1> ;        |-------------------------------------------| 
  3007                              <1> ;        |                                           |
  3008                              <1> ;        |-------------------------------------------|
  3009                              <1> ;        |                                           |
  3010                              <1> ;        |-------------------------------------------|
  3011                              <1> ;        |                                           |
  3012                              <1> ;        |-------------------------------------------| 
  3013                              <1> ;  3     |                                           | 
  3014                              <1> ;        |                                           |  
  3015                              <1> ;
  3016                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  3017                              <1> 
  3018                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  3019                              <1> 
  3020                              <1> ;Entry
  3021                              <1> ;         15                    7                   0
  3022                              <1> ;  1     |-------------------------------------------|
  3023                              <1> ;        |   	     i-number of open file           |
  3024                              <1> ;        |-------------------------------------------| 
  3025                              <1> ;        |        high word of 32 bit i-number       |
  3026                              <1> ;        |-------------------------------------------|
  3027                              <1> ;        | open mode & status  |   device number     |
  3028                              <1> ;        |-------------------------------------------|
  3029                              <1> ;        |    reserved byte    |     open count      |
  3030                              <1> ;        |-------------------------------------------| 
  3031                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3032                              <1> ;        |-------------------------------------------|
  3033                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3034                              <1> ;        |-------------------------------------------|
  3035                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3036                              <1> ;        |-------------------------------------------|
  3037                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3038                              <1> ;        |-------------------------------------------|
  3039                              <1> ;  2     |                                           |
  3040                              <1> ;        |-------------------------------------------| 
  3041                              <1> ;        |                                           |
  3042                              <1> ;        |-------------------------------------------|
  3043                              <1> ;        |                                           |
  3044                              <1> ;        |-------------------------------------------|
  3045                              <1> ;        |                                           |
  3046                              <1> ;        |-------------------------------------------| 
  3047                              <1> ;        |                                           | 
  3048                              <1> 
  3049                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  3050                              <1> ; (file structure has been moved from here to 'sysdefs.s'
  3051                              <1> ;	to overcome NASM's bss addressing bug !!!)
  3052                              <1> ; (('ux.s' bss section addresses are being overlapped
  3053                              <1> ;    when file file structure is defined in 'ux.s'))
  3054                              <1> 
  3055                              <1> %if 0
  3056                              <1> 
  3057                              <1> ; 22/11/2021
  3058                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision
  3059                              <1> 
  3060                              <1> struc file	; open files (fsp) structure
  3061                              <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  3062                              <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  3063                              <1>   .drive:  resb 1  ; logical drive (disk) number
  3064                              <1>   .flags:  resb 1  ; open mode and status
  3065                              <1>   .count:  resb 1  ; number of processes that have file open
  3066                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  3067                              <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  3068                              <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  3069                              <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  3070                              <1>  .size:  ; = 16		
  3071                              <1> endstruc
  3072                              <1> 
  3073                              <1> %endif
  3074                              <1> 
  3075                              <1> ; 01/01/2022
  3076                              <1> ; 22/11/2021
  3077                              <1> ;fp.size equ file.size
  3078                              <1> 
  3079                              <1> ; 02/01/2022
  3080 00007248 <res 320h>          <1> fsp:	resb nfiles*16 ; (NFILES*fp.size)
  3081                              <1> ; 01/01/2022
  3082                              <1> ; 22/11/2021 (16/05/2021)
  3083                              <1> ;fsp:	resb NFILES*16 ; (NFILES*fp.size)
  3084                              <1> ; 15/04/2015
  3085                              <1> ;fsp:	resb nfiles*10 ; 11/05/2015 (8 -> 10)
  3086                              <1> 
  3087 00007568 <res 20h>           <1> bufp:	resd (nbuf+2) ; will be initialized 
  3088 00007588 ????????            <1> ii:	resd 1 ; 22/11/2021 ; 32 bit inode number (high word is 0)
  3089                              <1> ; 22/11/2021
  3090 0000758C ??                  <1> idev:	resb 1 ; logical drive number of current inode, [ii]
  3091 0000758D ??                  <1> cdev:	resb 1 ; current logical drive number for current user
  3092                              <1> 
  3093                              <1> ; 18/05/2015
  3094                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  3095                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  3096                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  3097                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  3098                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  3099                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  3100                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  3101                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  3102                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  3103                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  3104                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  3105 0000758E ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  3106                              <1> 	        ; as above, for physical drives numbers in following table
  3107 0000758F ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  3108                              <1> ; 15/04/2015
  3109 00007590 ??                  <1> active:	 resb 1 
  3110 00007591 ??                  <1> 	 resb 1 ; 09/06/2015
  3111 00007592 ????                <1> mpid:	 resw 1
  3112                              <1> ; 22/11/2021 (32 bit inode numbers)
  3113 00007594 ????????            <1> rootdir: resd 1
  3114 00007598 ????????            <1> mnti:	 resd 1
  3115                              <1> 
  3116                              <1> ; 14/02/2014
  3117                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  3118                              <1> ;		      Single level run queue
  3119                              <1> ;		      (in order to solve sleep/wakeup lock)
  3120 0000759C ????                <1> runq:	resw 1
  3121 0000759E ??                  <1> imod:	resb 1
  3122 0000759F ??                  <1> imodx:	resb 1 ; 09/01/2022 - Retro UNIX 386 v1.2
  3123 000075A0 ??                  <1> smod:	resb 1
  3124 000075A1 ??                  <1> mmod:	resb 1
  3125                              <1> ;	resb 1 ; 09/01/2022 
  3126 000075A2 ??                  <1> sysflg:	resb 1
  3127                              <1> 
  3128 000075A3 ??                  <1> alignb 4
  3129                              <1> 
  3130                              <1> user:
  3131                              <1> 	; 01/01/2022
  3132                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3133                              <1> 	; 24/10/2021
  3134                              <1> 	; 18/10/2021
  3135                              <1> 	; 10/06/2021
  3136                              <1> 	; 30/05/2021
  3137                              <1> 	; 29/05/2021
  3138                              <1> 	; 21/05/2021
  3139                              <1> 	; 20/05/2021
  3140                              <1> 	; 16/05/2021
  3141                              <1> 	; 01/05/2021
  3142                              <1> 	; 27/03/2021
  3143                              <1> 	; 17/04/2020, 28/04/2020
  3144                              <1> 	; 25/03/2020, 28/03/2020
  3145                              <1> 	; 20/03/2020, 22/03/2020, 23/03/2020
  3146                              <1> 	; 05/03/2020, 08/03/2020, 14/03/2020
  3147                              <1> 	; 07/02/2020 - Retro UNIX 386 v2
  3148                              <1> 	;
  3149                              <1> 	; 27/02/2017 - TRDOS 386
  3150                              <1> 	; 13/01/2017 - TRDOS 386
  3151                              <1> 	; 10/01/2017 - TRDOS 386
  3152                              <1> 	; 19/12/2016 - TRDOS 386	
  3153                              <1> 	; 21/05/2016 - TRDOS 386 (TRDOS v2.0) 
  3154                              <1> 	; 	       [u.pri] usage method modification
  3155                              <1> 	;
  3156                              <1> 	; 04/12/2015 - Retro UNIX 386 v1.1 (14 byte file/directory names)
  3157                              <1> 	; 18/10/2015
  3158                              <1> 	; 12/10/2015
  3159                              <1> 	; 21/09/2015
  3160                              <1> 	; 24/07/2015
  3161                              <1> 	; 16/06/2015
  3162                              <1> 	; 09/06/2015
  3163                              <1> 	; 11/05/2015
  3164                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  3165                              <1> 	; 10/10/2013
  3166                              <1> 	; 11/03/2013. 
  3167                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  3168                              <1> 	;u.
  3169                              <1> 
  3170 000075A4 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  3171 000075A8 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  3172 000075AC ????????            <1> 	u.r0:	  resd 1 ; eax
  3173 000075B0 ????                <1> 	u.cdir:	  resw 1
  3174 000075B2 ????                <1> 		  resw 1 ; 28/03/2020 - reserved for 32 bit inode number
  3175                              <1> 	;u.cdrv:  resw 1 ; 17/04/2020 (dword alignment) 
  3176 000075B4 ??                  <1> 	u.cdrv:   resb 1 ; 01/05/2021
  3177 000075B5 ??                  <1> 		  resb 1 ; 01/05/2021 (dword alignment)
  3178 000075B6 <res Ah>            <1> 	u.fp:	  resb 10 ; Retro UNIX 386 v1
  3179                              <1> 	;u.fp:	  resb OPENFILES ; Retro UNIX 386 v2 ; 28/03/2020 
  3180                              <1> 	u.fsp:	  ; 16/05/2021
  3181 000075C0 ????????            <1> 	u.fofp:	  resd 1 ; 16/05/2021 (pointer to fsp entry)
  3182 000075C4 ????????            <1> 	u.dirp:	  resd 1
  3183 000075C8 ????????            <1> 	u.namep:  resd 1
  3184 000075CC ????????            <1> 	u.off:	  resd 1
  3185                              <1> 	;	  resd 1 ; 08/03/2020 - Retro UNIX 386 v2 - 64 bit fptr
  3186 000075D0 ????????            <1> 	u.base:	  resd 1
  3187 000075D4 ????????            <1> 	u.count:  resd 1
  3188 000075D8 ????????            <1> 	u.nread:  resd 1
  3189 000075DC ????????            <1> 	u.break:  resd 1 ; break
  3190                              <1> 	; 16/05/2021 (Retro UNIX 386 v2)
  3191 000075E0 ??                  <1> 	u.mode:   resb 1 ; 16/05/2021 (sysread, syswrite, 'rdwr' file mode)
  3192                              <1> 	; 10/01/2017 (TRDOS 386, relocation and dword alignment)
  3193                              <1> 	; tty number (rtty, rcvt, wtty)
  3194 000075E1 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  3195 000075E2 ????                <1> 	u.ttyp:	  resw 1 
  3196 000075E4 <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  3197                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  3198 000075F4 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  3199 000075F5 ??                  <1> 		  resb 1 ; 17/04/2020
  3200 000075F6 ??                  <1> 	u.pri:	  resb 1 ; Modification: 21/05/2016 (priority levels: 0, 1, 2)
  3201 000075F7 ??                  <1> 		  resb 1 ; 17/04/2020
  3202                              <1> 	; 10/06/2021
  3203                              <1> 	;u.signal: resw 1 ; 21/05/2021 - Retro UNIX 386 v2
  3204                              <1> 	;	  resw 1 ; reserved ; 21/05/2021	
  3205 000075F8 ????                <1> 	u.intr:	  resw 1
  3206 000075FA ????                <1> 	u.quit:	  resw 1
  3207                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  3208                              <1> 	;u.ilgins: resw 1 ; 10/01/2017
  3209                              <1> 	;u.cdrv:  resw 1 ; cdev ; 17/04/2020 (moved to up)
  3210                              <1> 	;u.uid:	  resb 1 ; uid
  3211                              <1> 	;u.ruid:  resb 1
  3212 000075FC ??                  <1> 	u.bsys:	  resb 1
  3213 000075FD ??                  <1> 	u.uno:	  resb 1
  3214 000075FE ????                <1>         u.uid:	  resw 1 ; uid	; 27/03/2021 - Retro UNIX 386 v2
  3215 00007600 ????                <1> 	u.ruid:	  resw 1	; 16 bit uid
  3216 00007602 ??                  <1> 	u.gid:	  resb 1 ; gid 	; 27/03/2021 - Retro UNIX 386 v2
  3217 00007603 ??                  <1> 	u.rgid:	  resb 1
  3218                              <1> 	; 20/05/2021 - Retro UNIX 386 v2
  3219 00007604 ????????            <1> 	u.procp:  resd 1 ; /* pointer to proc structure */		
  3220 00007608 ????????            <1> 	u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  3221 0000760C ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  3222 00007610 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  3223 00007614 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  3224                              <1> 		; 24/10/2021 (32 bit value for Retro UNIX 386 v2)
  3225 00007618 ????????            <1> 	u.pcount: resd 1 ; 20/05/2015 (byte -transfer- count for page)
  3226                              <1> 	;u.pncount: resw 1 
  3227                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  3228                              <1> 	;u.pnbase:  resd 1 
  3229                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  3230 0000761C ????                <1> 	u.rsvd:	  resw 1 ; 04/12/2021 (dword alignment)
  3231                              <1> 			 ; 09/06/2015
  3232 0000761E ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign
  3233                              <1> 		; 08/03/2020 (block device read/write flag for 'sioreg')		
  3234 0000761F ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  3235                              <1> 			 ; 24/07/2015 - 24/06/2015
  3236                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  3237                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  3238                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  3239                              <1>  			 ; 24/06/2015	  	
  3240                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  3241                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  3242                              <1> 	; last error number
  3243 00007620 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  3244                              <1> 			; Retro UNIX 8086/386 v1 feature only!
  3245                              <1> 			; 21/09/2015 (debugging - page fault analyze)
  3246 00007624 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  3247                              <1> 		; 29/05/2021 - Retro UNIX 386 v2, 2021 (sleep, psig)
  3248                              <1> ;	u.signal: resd 1 ; unix signal recognition (enabling, accepting) bits	
  3249                              <1> ;	u.srb:	  resb 1 ; signal handling/responding method
  3250                              <1> ;	u.snum:	  resb 1 ; signal number (last signal number)
  3251                              <1> ;	u.exit:	  resb 1 ; exit code ; 30/05/2021 - Retro UNIX 386 v2
  3252                              <1> ;	u.s_lock: resb 1 ; signal handling (phase) lock	
  3253                              <1> ;	u.s_addr: resd 1 ; Signal Response Byte or signal handler (callback) address
  3254                              <1> ;	u.s_time: resd 1 ; signal time in unix epoch format		
  3255                              <1> 		; 19/12/2016 (TRDOS 386)	
  3256                              <1> ;	u.tcb:	  resd 1 ; Timer callback address/flag which will be used by timer int
  3257                              <1> 		; 13/01/2017 (TRDOS 386)
  3258                              <1> ;	u.t_lock: resb 1 ; Timer interrupt (callback) lock (unlocked by 'sysrele')
  3259                              <1> ;	u.t_mode: resb 1 ; running mode during timer interrupt (0= system, 0FFh= user)
  3260                              <1> 		; 26/02/2017 (TRDOS 386)
  3261                              <1> ;	u.irqc:	  resb 1  ; Count of IRQ callback services (IRQs in use)
  3262                              <1> 		; 28/02/2017 (TRDOS 386) 
  3263                              <1> ;	u.irqwait: resb 1 ; IRQ waiting for callback service flag (IRQ number, If > 0)
  3264                              <1> ;	u.r_lock:  resb 1 ; 'IRQ callback service is in progress' flag (IRQ lock)
  3265                              <1> ;	u.r_mode:  resb 1 ; running mode during hardware interrupt
  3266                              <1> 		; 07/02/2020 - Retro UNIX 386 v2
  3267                              <1> ;	u.redir:  resb 1 ; device func redirection permitted by user (if u.redir > 0)
  3268                              <1> 		; 26/02/2020 - Retro UNIX 386 v2
  3269                              <1> ;	u.rwm:	  resb 1  ; read & write mode for devices/drives, 0 = direct, 1 = fs r/w 
  3270                              <1> 		; 24/02/2020 - Retro UNIX 386 v2
  3271                              <1> 		; 24/10/2021 (32 bit value)
  3272                              <1> ;	u.scount: resd 1 ; sub byte count ; 22/03/2020 
  3273                              <1> 		; 07/03/2020 - Retro UNIX 386 v2
  3274                              <1> ;	u.bps:	  resw 1 ; u.bps = bytes per sector, for readi and writei
  3275                              <1> ;		  resw 1 ; 24/10/2021 (32 bit value for using with 32 bit registers)	
  3276                              <1> 		; 23/03/2020 - Retro UNIX 386 v2
  3277                              <1> ;	u.timeout: resw 1 ; timeout setting (seconds) -for 'sleep'-
  3278                              <1> 		; 28/04/2020 - Retro UNIX 386 v2
  3279                              <1> ;	u.lock:	  resb 1 ; Device lock flag (bit 0 is for device/disk read/write)
  3280                              <1> 		; 24/04/2020
  3281                              <1> 		; 17/04/2020 - Retro UNIX 386 v2
  3282                              <1> ;	u.ifs:	  resb 1 ; (current) installable file system driver index number
  3283                              <1> 		; 25/03/2020
  3284                              <1> 		; 20/03/2020
  3285                              <1> 	;u.lcount: resd 1 ; last byte count for 'writei' (for restoring write count)	
  3286                              <1> 
  3287                              <1> 		; 08/03/2020 - Retro UNIX 386 v2 ('sioreg, 'readi')
  3288                              <1> 	;u.limit: resd 1  ; disk/file size limit for block device read/write ('sioreg')			
  3289                              <1> 	;	  resd 1  ; 08/03/2020 - 64 bit limit (disk size in bytes)
  3290                              <1> 	;	; 26/02/2020 - Retro UNIX 386 v2
  3291                              <1> 	;u.sector: resd 1  ; current sector (for readi and writei, device r/w)  		
  3292                              <1> 	;u.buffer: resd 1  ; current buffer (for readi and writei, device r/w) 
  3293                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3294                              <1> 	;u.devmm: resw 1 ; device major (hb) and minor (lb) numbers
  3295                              <1> 	;u.zero:  resw 1 ; 14/03/2020 - Must be ZERO for current version
  3296                              <1> 		; 22/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3297                              <1> ;	u.device: resd 1 ; (blk, chr) device description table (entry) address 	
  3298                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3299                              <1> ;	u.function: resd 1 ; device function (read, write)
  3300                              <1> 		; 22/03/2020 - Retro UNIX 386 v2, 2020 (readi, writei)
  3301                              <1> ;	u.buffer: resd 1  ; for saving buffer header address for 'poke'
  3302                              <1> ;	u.inode:  resw 1  ; for saving inode number of current (device) inode
  3303                              <1> ;		  resw 1  ; 18/10/2021 Retro UNIX 386 v2 - 32 bit inode number			
  3304                              <1> ;	u.idev:	  resb 1  ; for saving logical drv number of current (dev) inode
  3305                              <1> 		; 04/12/2021
  3306                              <1> ;	u.rsvd2:  resw 1  ; (for dword alignment)	
  3307                              <1> 		; 27/02/2017 (TRDOS 386) 
  3308                              <1> ;; 31/12/2021 - temporary !
  3309                              <1> ;	u.fpsave: resb 1  ; TRDOS 386, 'save/restore FPU registers' flag
  3310                              <1> alignb 4
  3311                              <1> 	; !! wrong sizing in TRDOS 386 v2.0.4 (in 'ubss.s', 28/02/2017) !! 
  3312                              <1> 	;u.fpregs: resb 94 ; 94 byte area for saving and restoring FPU registers
  3313                              <1> 	; 30/05/2021 - Retro UNIX 386 v2
  3314                              <1> ;	u.fpregs: resb 108 ; 108 byte area for saving and restoring FPU registers	
  3315                              <1> alignb 4
  3316                              <1> 
  3317                              <1> U_SIZE	equ $ - user
  3318                              <1> 
  3319                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  3320 00007628 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3321 0000762C ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3322 00007630 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  3323                              <1> ;ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec'
  3324                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'ncount')
  3325 00007634 ????????            <1> ncount: resd 1	; remain byte count in page for 'namei' & 'sysexec'
  3326                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  3327                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'argc')
  3328 00007638 ????????            <1> argc:	resd 1	; argument count for 'sysexec'
  3329 0000763C ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3330                              <1> 
  3331                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3332                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3333 00007640 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3334 00007641 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3335 00007642 ??                  <1> mget_rw: resb 1 ; 22/11/2021 
  3336 00007643 ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3337                              <1> 
  3338                              <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility
  3339                              <1> level:	resd 0  ; level, level+1, level+2, level+3  ; for 'mget' procedure
  3340                              <1> 
  3341                              <1> ; (02/01/2022)
  3342                              <1> ; 27/11/2021
  3343                              <1> ; these are will be used for disk block allocation ('alloc' proc)
  3344                              <1> free_map_offset: 
  3345 00007644 ????????            <1> 		resd 1
  3346 00007648 ????????            <1> free_map_index:	resd 1
  3347                              <1> free_map_sector:
  3348 0000764C ????????            <1> 		resd 1
  3349                              <1> ;free_map_buffer:
  3350                              <1> ;		resd 1
  3351                              <1> 
  3352                              <1> ; 12/01/2022
  3353                              <1> ; 27/11/2021 - temporary !
  3354                              <1> ;s.time:	resd 1
  3355                              <1> 
  3356                              <1> ;alignb 4
  3357                              <1> 
  3358                              <1> ; (02/01/2022)
  3359                              <1> ; 22/08/2015
  3360                              <1> ;buffer: resb nbuf * 520
  3361                              <1> 
  3362 00007650 ????????????????    <1> sb0:	resd 2
  3363                              <1> ;s:
  3364                              <1> ; (root disk) super block buffer
  3365                              <1> systm:
  3366                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatible super block
  3367                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3368                              <1> 	; 11/03/2013. 
  3369                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3370                              <1> 	;s.
  3371                              <1> 
  3372                              <1> 	;resw 1
  3373                              <1> 	;resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3374                              <1> 	;resw 1
  3375                              <1> 	;resb 32 ; 256+40 inodes ; original UNIX v1 value: 64
  3376                              <1> 	;s.time: resd 1
  3377                              <1> 	;s.syst: resd 1
  3378                              <1>         ;s.wait_: resd 1 ; wait
  3379                              <1> 	;s.idlet: resd 1
  3380                              <1> 	;s.chrgt: resd 1
  3381                              <1> 	;s.drerr: resw 1
  3382                              <1> 
  3383                              <1> 	; 27/11/2021
  3384 00007658 <res 200h>          <1> 	resb 512	
  3385                              <1> 
  3386                              <1> ;S_SIZE	equ $ - systm
  3387                              <1> 
  3388                              <1> 	;resb 512-S_SIZE ; 03/06/2015
  3389                              <1> 
  3390 00007858 ????????????????    <1> sb1:	resd 2
  3391                              <1> ; (mounted disk) super block buffer
  3392                              <1> mount:	
  3393 00007860 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3394                              <1> 
  3395                              <1> ; 21/03/2022
  3396                              <1> ; hard disk masterboot sector buffer
  3397 00007A60 ????????????????    <1> mbrbuf: resd 2
  3398 00007A68 <res 200h>          <1> 	resb 512
  3399                              <1> 
  3400                              <1> ; 10/01/2022
  3401 00007C68 <res 200h>          <1> dbli_buf: resb 512  ; double indir ptr buff for 'itrunc', 'tloop'
  3402 00007E68 <res 200h>          <1> trpi_buf: resb 512  ; triple indir ptr buff for 'itrunc', 'tloop'
  3403                              <1> 
  3404                              <1> ;/ ux -- unix
  3405                              <1> ;
  3406                              <1> ;systm:
  3407                              <1> ;
  3408                              <1> ;	.=.+2
  3409                              <1> ;	.=.+128.
  3410                              <1> ;	.=.+2
  3411                              <1> ;	.=.+64.
  3412                              <1> ;	s.time: .=.+4
  3413                              <1> ;	s.syst: .=.+4
  3414                              <1> ;	s.wait: .=.+4
  3415                              <1> ;	s.idlet:.=.+4
  3416                              <1> ;	s.chrgt:.=.+4
  3417                              <1> ;	s.drerr:.=.+2
  3418                              <1> ;inode:
  3419                              <1> ;	i.flgs: .=.+2
  3420                              <1> ;	i.nlks: .=.+1
  3421                              <1> ;	i.uid:  .=.+1
  3422                              <1> ;	i.size: .=.+2
  3423                              <1> ;	i.dskp: .=.+16.
  3424                              <1> ;	i.ctim: .=.+4
  3425                              <1> ;	i.mtim: .=.+4
  3426                              <1> ;	. = inode+32.
  3427                              <1> ;mount:	.=.+1024.
  3428                              <1> ;proc:
  3429                              <1> ;	p.pid:  .=.+[2*nproc]
  3430                              <1> ;	p.dska: .=.+[2*nproc]
  3431                              <1> ;	p.ppid: .=.+[2*nproc]
  3432                              <1> ;	p.break:.=.+[2*nproc]
  3433                              <1> ;	p.link: .=.+nproc
  3434                              <1> ;	p.stat: .=.+nproc
  3435                              <1> ;tty:
  3436                              <1> ;	. = .+[ntty*8.]
  3437                              <1> ;fsp:	.=.+[nfiles*8.]
  3438                              <1> ;bufp:	.=.+[nbuf*2]+6
  3439                              <1> ;sb0:	.=.+8
  3440                              <1> ;sb1:	.=.+8
  3441                              <1> ;swp:	.=.+8
  3442                              <1> ;ii:	.=.+2
  3443                              <1> ;idev:	.=.+2
  3444                              <1> ;cdev:	.=.+2
  3445                              <1> ;deverr: .=.+12.
  3446                              <1> ;active: .=.+2
  3447                              <1> ;rfap:	.=.+2
  3448                              <1> ;rkap:	.=.+2
  3449                              <1> ;tcap:	.=.+2
  3450                              <1> ;tcstate:.=.+2
  3451                              <1> ;tcerrc: .=.+2
  3452                              <1> ;mnti:	.=.+2
  3453                              <1> ;mntd:	.=.+2
  3454                              <1> ;mpid:	.=.+2
  3455                              <1> ;clockp: .=.+2
  3456                              <1> ;rootdir:.=.+2
  3457                              <1> ;toutt:	.=.+16.
  3458                              <1> ;touts: .=.+32.
  3459                              <1> ;runq:	.=.+6
  3460                              <1> ;
  3461                              <1> ;wlist:	.=.+40.
  3462                              <1> ;cc:	.=.+30.
  3463                              <1> ;cf:	.=.+31.
  3464                              <1> ;cl:	.=.+31.
  3465                              <1> ;clist:	.=.+510.
  3466                              <1> ;imod:	.=.+1
  3467                              <1> ;smod:	.=.+1
  3468                              <1> ;mmod:	.=.+1
  3469                              <1> ;uquant: .=.+1
  3470                              <1> ;sysflg: .=.+1
  3471                              <1> ;pptiflg:.=.+1
  3472                              <1> ;ttyoch: .=.+1
  3473                              <1> ; .even
  3474                              <1> ; .=.+100.; sstack:
  3475                              <1> ;buffer: .=.+[ntty*140.]
  3476                              <1> ;	.=.+[nbuf*520.]
  3477                              <1> ;
  3478                              <1> ; . = core-64.
  3479                              <1> ;user:
  3480                              <1> ;	u.sp:    .=.+2
  3481                              <1> ;	u.usp:   .=.+2
  3482                              <1> ;	u.r0:    .=.+2
  3483                              <1> ;	u.cdir:  .=.+2
  3484                              <1> ;	u.fp:    .=.+10.
  3485                              <1> ;	u.fofp:  .=.+2
  3486                              <1> ;	u.dirp:  .=.+2
  3487                              <1> ;	u.namep: .=.+2
  3488                              <1> ;	u.off:   .=.+2
  3489                              <1> ;	u.base:  .=.+2
  3490                              <1> ;	u.count: .=.+2
  3491                              <1> ;	u.nread: .=.+2
  3492                              <1> ;	u.break: .=.+2
  3493                              <1> ;	u.ttyp:  .=.+2
  3494                              <1> ;	u.dirbuf:.=.+10.
  3495                              <1> ;	u.pri:   .=.+2
  3496                              <1> ;	u.intr:  .=.+2
  3497                              <1> ;	u.quit:  .=.+2
  3498                              <1> ;	u.emt:   .=.+2
  3499                              <1> ;	u.ilgins:.=.+2
  3500                              <1> ;	u.cdev:  .=.+2
  3501                              <1> ;	u.uid:   .=.+1
  3502                              <1> ;	u.ruid:  .=.+1
  3503                              <1> ;	u.bsys:  .=.+1
  3504                              <1> ;	u.uno:   .=.+1
  3505                              <1> ;. = core
  2755                                  
  2756                                  ; 27/12/2021
  2757 00008068 <res C30h>              buffer:	resb (nbuf*520)
  2758                                  
  2759                                  bss_end:
  2760                                  
  2761                                  ; 12/12/2021
  2762                                  BSS_SIZE equ bss_end - bss_start
  2763                                  
  2764                                  ; 27/12/2013
  2765                                  _end: ; end of kernel code (and read only data, just before bss)
