     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: 16/02/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[7A6A]              	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[146D]              	mov	[mem_1m_1k], cx
   175 00000017 8916[186D]              	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[7D6A]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   242 0000008A 8816[7C6A]          <1>         mov     [last_drv], dl  ; last hard disk number
   243 0000008E BB[006A]            <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[7E6A]            <1> 	mov	si, fd0_type
   261                              <1> L3:
   262                              <1> 	; 14/01/2015
   263 0000009F 8816[7B6A]          <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[7E6A]          <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[7D6A]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[7B6A]          <1>         mov     [drv], dl
   297 000000CB 8816[7C6A]          <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[7D6A]          <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[7B6A]          <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[7B6A]          <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[7B6A]          <1> 	inc	byte [drv]
   359 0000013C BB[006A]            <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[7D6A]            <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[7B6A]          <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[7B6A]          <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[806A]          <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[7E6A]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   421 00000193 81C3[CA6A]          <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[CA6A]          <1> 	sub	bx, drv.status
   430 000001A5 C1E302              <1> 	shl	bx, 2
   431 000001A8 81C3[AE6A]          <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[806A]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   536 00000233 808F[CC6A]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[CC6A]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[7C6A]          <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[7B6A]          <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[CA6A]          <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[CA6A]          <1> 	sub	bx, drv.status
   736 00000289 D0E3                <1> 	shl	bl, 1
   737 0000028B 81C3[846A]          <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[846A]          <1> 	sub	bx, drv.cylinders
   742 00000297 81C3[926A]          <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[926A]          <1>         sub     bx, drv.heads
   748 000002A6 81C3[A06A]          <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[A06A]          <1>         sub     bx, drv.spt
   753 000002B5 D1E3                <1> 	shl	bx, 1
   754 000002B7 81C3[AE6A]          <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 B98E36                  	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[A067]                  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 B91B070000              	mov	ecx, BSS_SIZE/4
   314 00000328 BF[206D0000]            	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[146D0000]          	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[906F0000]          	mov	[free_pages], ecx
   342 00000347 8B15[186D0000]          	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[906F0000]          	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[8C6F0000]            	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[A06F0000]            	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[886F0000]          	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[986F0000]            	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[A06F0000]          	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[906F0000]          	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[8C6F0000]          	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[906F0000]          	sub	[free_pages], ecx ; 07/11/2014
   483                                  	;
   484 00000420 8B35[886F0000]          	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[886F0000]          	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[8C6F0000]          	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[9C6F0000]            	mov	[first_page], eax
   564 0000048A A3[946F0000]            	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[886F0000]                    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[E06A0000]            	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[AC670000]            	mov	esi, ilist
   657 000004E5 8D3D[206D0000]          	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[74090000]            	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[A6670000]        	lidt 	[idtd]
   703                                  	;
   704                                  	; TSS descriptor setup ; 24/03/2015
   705 0000053B B8[206F0000]            	mov	eax, task_state_segment
   706 00000540 66A3[9A670000]          	mov	[gdt_tss0], ax
   707 00000546 C1C010                  	rol	eax, 16
   708 00000549 A2[9C670000]            	mov	[gdt_tss1], al
   709 0000054E 8825[9F670000]          	mov	[gdt_tss2], ah
   710 00000554 66C705[866F0000]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[8C6F0000]          	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[246F0000]          	mov	[tss.esp0], esp
   744 00000582 66C705[286F0000]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 E81E0F0000              	call	set_cpos
   771                                  	;
   772                                  	; 06/11/2014
   773                                  	; Temporary Code
   774                                  	;
   775 000005A6 E893100000              	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[806A0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   782 000005B2 668B1D[7E6A0000]        	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[C96B0000]            	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 E8E40D0000              	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 E8681F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   820                                  	;
   821 000005E7 09D2                    	or	edx, edx
   822 000005E9 7407                            jz      short di3
   823                                  di2:
   824 000005EB E8A41F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   825 000005F0 72D0                            jc      short setup_error
   826                                  di3:
   827 000005F2 E81B100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   828                                  	;
   829 000005F7 E8D2600000              	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[B66F0000]          	mov 	ah, [ptty] ; active (current) video page
   842 0000060B E8075E0000              	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 E8852C0000              	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[B66F0000]          	mov	bl, [ptty]	; active_page
   871 00000625 89DE                    	mov	esi, ebx
   872 00000627 66D1E6                  	shl 	si, 1
   873 0000062A 81C6[B86F0000]          	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 E8700D0000              	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[13070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   975                                  	;
   976 0000067A 3B0D[886F0000]          	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[A8740000]            	mov 	[u.r0], eax
   981 00000687 89E1                    	mov	ecx, esp
   982 00000689 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   983 0000068C 890D[A0740000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   984 00000692 8925[A4740000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   985                                  	;
   986 00000698 8B0D[886F0000]          	mov	ecx, [k_page_dir]
   987 0000069E 0F22D9                  	mov	cr3, ecx
   988                                  T3:
   989 000006A1 FB                      	sti				; INTERRUPTS BACK ON
   990 000006A2 66FF05[04700000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   991 000006A9 7507                    	JNZ	short T4		; GO TO TEST_DAY
   992 000006AB 66FF05[06700000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   993                                  T4:					; TEST_DAY
   994 000006B2 66833D[06700000]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[04700000]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[04700000]            	mov	[TIMER_LH], eax
  1005                                  	;	
  1006 000006CE C605[08700000]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[0B700000]            	mov	al, [MOTOR_COUNT]
  1017 000006DC FEC8                    	dec	al
  1018                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1019 000006DE A2[0B700000]            	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[0A700000]          	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[13070000]            	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 [17070000]              	dd 	u_timer			; 14/05/2015
  1065                                  	;dd	clock
  1066                                  
  1067                                  ; 14/10/2015
  1068 00000713 00000000                cr3reg: dd 0
  1069                                  
  1070                                  	; 04/12/2021 - Retro UNIX 386 v1.2
  1071                                  	; 06/02/2015
  1072                                  	; 07/09/2014
  1073                                  	; 21/08/2014
  1074                                  u_timer:
  1075                                  ;timer_int:	; IRQ 0
  1076                                  	; 06/02/2015
  1077                                  	;push	eax
  1078                                  	;push	edx
  1079                                  	;push	ecx
  1080                                  	;push	ebx
  1081                                  	;push	ds
  1082                                  	;push	es
  1083                                  	;mov	eax, KDATA
  1084                                  	;mov	ds, ax
  1085                                  	;mov	es, ax
  1086 00000717 FF05[CC6F0000]          	inc	dword [tcount]
  1087 0000071D BB[526B0000]            	mov	ebx, tcountstr + 4
  1088                                  	;mov	ax, [tcount]
  1089                                  	; 04/12/2021
  1090 00000722 A1[CC6F0000]            	mov	eax, [tcount]
  1091 00000727 B90A000000              	mov	ecx, 10
  1092                                  rp_divtcnt:
  1093 0000072C 31D2                    	xor	edx, edx
  1094 0000072E F7F1                    	div	ecx
  1095 00000730 80C230                  	add	dl, 30h
  1096 00000733 8813                    	mov	[ebx], dl
  1097                                  	;or	ax, ax
  1098                                  	; 04/12/2021
  1099 00000735 09C0                    	or	eax, eax
  1100 00000737 7403                    	jz	short print_lzero
  1101 00000739 4B                      	dec	ebx
  1102 0000073A EBF0                    	jmp	short rp_divtcnt
  1103                                  print_lzero:
  1104 0000073C 81FB[4E6B0000]          	cmp	ebx, tcountstr
  1105 00000742 7606                    	jna	short print_tcount
  1106 00000744 4B                      	dec	ebx
  1107 00000745 C60330                   	mov	byte [ebx], 30h
  1108 00000748 EBF2                    	jmp	short print_lzero
  1109                                  print_tcount:
  1110 0000074A 56                      	push	esi
  1111 0000074B 57                      	push	edi
  1112 0000074C BE[2A6B0000]            	mov	esi, timer_msg ; Timer interrupt message
  1113                                  	; 07/09/2014
  1114                                  	;mov	bx, 1	; Video page 1
  1115                                  	; 04/12/2021
  1116 00000751 29DB                    	sub	ebx, ebx
  1117                                  	;inc	bl ; ebx = 1
  1118                                  	; 02/01/2022
  1119 00000753 B306                    	mov	bl, 6	; Video page 6
  1120                                  ptmsg:
  1121 00000755 AC                      	lodsb
  1122 00000756 08C0                    	or	al, al
  1123 00000758 740D                    	jz	short ptmsg_ok
  1124 0000075A 56                      	push	esi
  1125                                  	;push	bx
  1126                                  	; 04/12/2021
  1127 0000075B 53                              push	ebx
  1128 0000075C B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1129 0000075E E8570C0000              	call 	write_tty
  1130                                  	;pop	bx
  1131                                  	; 04/12/2021
  1132 00000763 5B                      	pop	ebx
  1133 00000764 5E                      	pop	esi
  1134 00000765 EBEE                    	jmp	short ptmsg
  1135                                  	;; 27/08/2014
  1136                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1137                                  	;call	printk
  1138                                  	;
  1139                                  ptmsg_ok:
  1140                                  	; 07/09/2014
  1141                                  	;xor	dx, dx		; column 0, row 0
  1142                                  	; 04/12/2021
  1143 00000767 31D2                    	xor	edx, edx
  1144 00000769 E8560D0000              	call	set_cpos	; set cursor position to 0,0 
  1145                                  	; 23/02/2015
  1146                                  	; 25/08/2014
  1147                                  	;mov	ebx, scounter		; (seconds counter)
  1148                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1149                                  ;	dec	byte [scounter+1]
  1150                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1151                                  ;	jns	short u_timer_retn
  1152                                  	; 26/02/2015
  1153                                  ;	call	rtc_p
  1154                                  ;	mov	ebx, scounter		; (seconds counter)
  1155                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1156                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1157                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1158                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1159                                  ;	mov	byte [ebx], 5
  1160                                  ;	inc	byte [ebx+1] ; 19
  1161                                  ;;timer_eoi:
  1162                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1163                                  ;;	out	20h, al	; 8259 PORT
  1164                                  	;
  1165                                  ;u_timer_retn:  ; 06/02/2015
  1166 0000076E 5F                      	pop	edi
  1167 0000076F 5E                      	pop	esi
  1168                                  	;pop	es
  1169                                  	;pop	ds
  1170                                  	;pop	ebx
  1171                                  	;pop	ecx
  1172                                  	;pop	edx
  1173                                  	;pop	eax
  1174                                  	;iret
  1175 00000770 C3                      	retn	; 06/02/2015
  1176                                  
  1177                                  	; 28/08/2014
  1178                                  irq0:
  1179 00000771 6A00                            push 	dword 0
  1180 00000773 EB48                    	jmp	short which_irq
  1181                                  irq1:
  1182 00000775 6A01                            push 	dword 1
  1183 00000777 EB44                    	jmp	short which_irq
  1184                                  irq2:
  1185 00000779 6A02                            push 	dword 2
  1186 0000077B EB40                    	jmp	short which_irq
  1187                                  irq3:
  1188                                  	; 20/11/2015
  1189                                  	; 24/10/2015
  1190 0000077D 2EFF15[C5390000]        	call	dword [cs:com2_irq3]
  1191 00000784 6A03                    	push 	dword 3
  1192 00000786 EB35                    	jmp	short which_irq
  1193                                  irq4:
  1194                                  	; 20/11/2015
  1195                                  	; 24/10/2015
  1196 00000788 2EFF15[C1390000]        	call	dword [cs:com1_irq4]
  1197 0000078F 6A04                            push 	dword 4
  1198 00000791 EB2A                    	jmp	short which_irq
  1199                                  irq5:
  1200 00000793 6A05                            push 	dword 5
  1201 00000795 EB26                    	jmp	short which_irq
  1202                                  irq6:
  1203 00000797 6A06                            push 	dword 6
  1204 00000799 EB22                    	jmp	short which_irq
  1205                                  irq7:
  1206 0000079B 6A07                            push 	dword 7
  1207 0000079D EB1E                    	jmp	short which_irq
  1208                                  irq8:
  1209 0000079F 6A08                            push 	dword 8
  1210 000007A1 EB1A                    	jmp	short which_irq
  1211                                  irq9:
  1212 000007A3 6A09                            push 	dword 9
  1213 000007A5 EB16                    	jmp	short which_irq
  1214                                  irq10:
  1215 000007A7 6A0A                            push 	dword 10
  1216 000007A9 EB12                    	jmp	short which_irq
  1217                                  irq11:
  1218 000007AB 6A0B                            push 	dword 11
  1219 000007AD EB0E                    	jmp	short which_irq
  1220                                  irq12:
  1221 000007AF 6A0C                            push 	dword 12
  1222 000007B1 EB0A                    	jmp	short which_irq
  1223                                  irq13:
  1224 000007B3 6A0D                            push 	dword 13
  1225 000007B5 EB06                    	jmp	short which_irq
  1226                                  irq14:
  1227 000007B7 6A0E                            push 	dword 14
  1228 000007B9 EB02                    	jmp	short which_irq
  1229                                  irq15:
  1230 000007BB 6A0F                            push 	dword 15
  1231                                  	;jmp	short which_irq
  1232                                  
  1233                                  	; 19/10/2015
  1234                                  	; 29/08/2014
  1235                                  	; 21/08/2014
  1236                                  which_irq:
  1237 000007BD 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1238 000007C0 53                      	push	ebx
  1239 000007C1 56                      	push	esi
  1240 000007C2 57                      	push	edi
  1241 000007C3 1E                      	push 	ds
  1242 000007C4 06                      	push 	es
  1243                                  	;
  1244 000007C5 88C3                    	mov	bl, al
  1245                                  	;
  1246 000007C7 B810000000              	mov	eax, KDATA
  1247 000007CC 8ED8                    	mov	ds, ax
  1248 000007CE 8EC0                    	mov	es, ax
  1249                                  	; 19/10/2015
  1250 000007D0 FC                      	cld
  1251                                          ; 27/08/2014
  1252 000007D1 8105[D86A0000]A000-             add     dword [scr_row], 0A0h
  1252 000007D9 0000               
  1253                                  	;
  1254 000007DB B417                    	mov	ah, 17h	; blue (1) background, 
  1255                                  			; light gray (7) forecolor
  1256 000007DD 8B3D[D86A0000]                  mov     edi, [scr_row]
  1257 000007E3 B049                    	mov	al, 'I'
  1258 000007E5 66AB                    	stosw
  1259 000007E7 B052                    	mov	al, 'R'
  1260 000007E9 66AB                    	stosw
  1261 000007EB B051                    	mov	al, 'Q'
  1262 000007ED 66AB                    	stosw
  1263 000007EF B020                    	mov	al, ' '
  1264 000007F1 66AB                    	stosw
  1265 000007F3 88D8                    	mov	al, bl
  1266 000007F5 3C0A                    	cmp	al, 10
  1267 000007F7 7208                    	jb	short iix
  1268 000007F9 B031                    	mov	al, '1'
  1269 000007FB 66AB                    	stosw
  1270 000007FD 88D8                    	mov	al, bl
  1271 000007FF 2C0A                    	sub	al, 10
  1272                                  iix:
  1273 00000801 0430                    	add	al, '0'
  1274 00000803 66AB                    	stosw
  1275 00000805 B020                    	mov	al, ' '
  1276 00000807 66AB                    	stosw
  1277 00000809 B021                    	mov	al, '!'
  1278 0000080B 66AB                    	stosw
  1279 0000080D B020                    	mov	al, ' '
  1280 0000080F 66AB                    	stosw
  1281                                  	; 23/02/2015
  1282 00000811 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1283                                  	;jna	iiret
  1284                                  	; 04/12/2021
  1285 00000814 7604                    	jna	short iiz
  1286                                  iiy:
  1287 00000816 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1288 00000818 E6A0                    	out	0A0h, al ; the 2nd 8259
  1289                                  iiz:
  1290 0000081A E983010000              	jmp     iiret
  1291                                  	;
  1292                                  	; 22/08/2014
  1293                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1294                                  	;out	20h, al	; 8259 PORT
  1295                                  	;
  1296                                  	;pop	es
  1297                                  	;pop	ds
  1298                                  	;pop	edi
  1299                                  	;pop	esi
  1300                                  	;pop	ebx
  1301                                  	;pop 	eax
  1302                                  	;iret
  1303                                  
  1304                                  	; 02/04/2015
  1305                                  	; 25/08/2014
  1306                                  exc0:
  1307 0000081F 6A00                            push 	dword 0
  1308 00000821 E990000000                      jmp     cpu_except
  1309                                  exc1:
  1310 00000826 6A01                            push 	dword 1
  1311 00000828 E989000000                      jmp     cpu_except
  1312                                  exc2:
  1313 0000082D 6A02                            push 	dword 2
  1314 0000082F E982000000                      jmp     cpu_except
  1315                                  exc3:
  1316 00000834 6A03                            push 	dword 3
  1317 00000836 EB7E                            jmp     cpu_except
  1318                                  exc4:
  1319 00000838 6A04                            push 	dword 4
  1320 0000083A EB7A                            jmp     cpu_except
  1321                                  exc5:
  1322 0000083C 6A05                            push 	dword 5
  1323 0000083E EB76                            jmp     cpu_except
  1324                                  exc6:
  1325 00000840 6A06                            push 	dword 6
  1326 00000842 EB72                            jmp     cpu_except
  1327                                  exc7:
  1328 00000844 6A07                            push 	dword 7
  1329 00000846 EB6E                            jmp     cpu_except
  1330                                  exc8:
  1331                                  	; [esp] = Error code
  1332 00000848 6A08                            push 	dword 8
  1333 0000084A EB5C                            jmp     cpu_except_en
  1334                                  exc9:
  1335 0000084C 6A09                            push 	dword 9
  1336 0000084E EB66                            jmp     cpu_except
  1337                                  exc10:
  1338                                  	; [esp] = Error code
  1339 00000850 6A0A                            push 	dword 10
  1340 00000852 EB54                            jmp     cpu_except_en
  1341                                  exc11:
  1342                                  	; [esp] = Error code
  1343 00000854 6A0B                            push 	dword 11
  1344 00000856 EB50                            jmp     cpu_except_en
  1345                                  exc12:
  1346                                  	; [esp] = Error code
  1347 00000858 6A0C                            push 	dword 12
  1348 0000085A EB4C                            jmp     cpu_except_en
  1349                                  exc13:
  1350                                  	; [esp] = Error code
  1351 0000085C 6A0D                            push 	dword 13
  1352 0000085E EB48                            jmp     cpu_except_en
  1353                                  exc14:
  1354                                  	; [esp] = Error code
  1355 00000860 6A0E                            push 	dword 14
  1356 00000862 EB44                    	jmp	short cpu_except_en
  1357                                  exc15:
  1358 00000864 6A0F                            push 	dword 15
  1359 00000866 EB4E                            jmp     cpu_except
  1360                                  exc16:
  1361 00000868 6A10                            push 	dword 16
  1362 0000086A EB4A                            jmp     cpu_except
  1363                                  exc17:
  1364                                  	; [esp] = Error code
  1365 0000086C 6A11                            push 	dword 17
  1366 0000086E EB38                    	jmp	short cpu_except_en
  1367                                  exc18:
  1368 00000870 6A12                            push 	dword 18
  1369 00000872 EB42                    	jmp	short cpu_except
  1370                                  exc19:
  1371 00000874 6A13                            push 	dword 19
  1372 00000876 EB3E                    	jmp	short cpu_except
  1373                                  exc20:
  1374 00000878 6A14                            push 	dword 20
  1375 0000087A EB3A                    	jmp	short cpu_except
  1376                                  exc21:
  1377 0000087C 6A15                            push 	dword 21
  1378 0000087E EB36                    	jmp	short cpu_except
  1379                                  exc22:
  1380 00000880 6A16                            push 	dword 22
  1381 00000882 EB32                    	jmp	short cpu_except
  1382                                  exc23:
  1383 00000884 6A17                            push 	dword 23
  1384 00000886 EB2E                    	jmp	short cpu_except
  1385                                  exc24:
  1386 00000888 6A18                            push 	dword 24
  1387 0000088A EB2A                    	jmp	short cpu_except
  1388                                  exc25:
  1389 0000088C 6A19                            push 	dword 25
  1390 0000088E EB26                    	jmp	short cpu_except
  1391                                  exc26:
  1392 00000890 6A1A                            push 	dword 26
  1393 00000892 EB22                    	jmp	short cpu_except
  1394                                  exc27:
  1395 00000894 6A1B                            push 	dword 27
  1396 00000896 EB1E                    	jmp	short cpu_except
  1397                                  exc28:
  1398 00000898 6A1C                            push 	dword 28
  1399 0000089A EB1A                    	jmp	short cpu_except
  1400                                  exc29:
  1401 0000089C 6A1D                            push 	dword 29
  1402 0000089E EB16                    	jmp	short cpu_except
  1403                                  exc30:
  1404 000008A0 6A1E                            push 	dword 30
  1405 000008A2 EB04                    	jmp	short cpu_except_en
  1406                                  exc31:
  1407 000008A4 6A1F                            push 	dword 31
  1408 000008A6 EB0E                            jmp     short cpu_except
  1409                                  
  1410                                  	; 02/01/2022 (Retro UNIX 386 v1.2)
  1411                                  	; 19/10/2015
  1412                                  	; 19/09/2015
  1413                                  	; 01/09/2015
  1414                                  	; 28/08/2015
  1415                                  	; 28/08/2014
  1416                                  cpu_except_en:
  1417 000008A8 87442404                	xchg	eax, [esp+4] ; Error code
  1418 000008AC 36A3[38700000]          	mov	[ss:error_code], eax
  1419 000008B2 58                      	pop	eax  ; Exception number
  1420 000008B3 870424                  	xchg	eax, [esp]
  1421                                  		; eax = eax before exception
  1422                                  		; [esp] -> exception number
  1423                                  		; [esp+4] -> EIP to return
  1424                                  	; 19/10/2015
  1425                                  	; 19/09/2015
  1426                                  	; 01/09/2015
  1427                                  	; 28/08/2015
  1428                                  	; 29/08/2014
  1429                                  	; 28/08/2014
  1430                                  	; 25/08/2014
  1431                                  	; 21/08/2014
  1432                                  cpu_except:	; CPU Exceptions
  1433 000008B6 FC                      	cld
  1434 000008B7 870424                  	xchg	eax, [esp] 
  1435                                  		; eax = Exception number
  1436                                  		; [esp] = eax (before exception)
  1437 000008BA 53                      	push	ebx
  1438 000008BB 56                      	push	esi
  1439 000008BC 57                      	push	edi
  1440 000008BD 1E                      	push 	ds
  1441 000008BE 06                      	push 	es
  1442                                  	; 28/08/2015
  1443 000008BF 66BB1000                	mov	bx, KDATA
  1444 000008C3 8EDB                    	mov	ds, bx
  1445 000008C5 8EC3                    	mov	es, bx
  1446 000008C7 0F20DB                  	mov	ebx, cr3
  1447 000008CA 53                      	push	ebx ; (*) page directory
  1448                                  	; 19/10/2015
  1449 000008CB FC                      	cld
  1450                                  	; 25/03/2015
  1451 000008CC 8B1D[886F0000]          	mov	ebx, [k_page_dir]
  1452 000008D2 0F22DB                  	mov	cr3, ebx
  1453                                  	; 28/08/2015
  1454 000008D5 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1455 000008D8 7513                    	jne	short cpu_except_nfp
  1456 000008DA E87A270000              	call	page_fault_handler
  1457 000008DF 21C0                    	and 	eax, eax
  1458                                  	;jz	iiretp ; 01/09/2015
  1459                                  	; 02/01/2022
  1460 000008E1 7505                    	jnz	short cpu_except_pf
  1461 000008E3 E9B6000000              	jmp	iiretp
  1462                                  cpu_except_pf:
  1463 000008E8 B80E000000              	mov	eax, 0Eh ; 14
  1464                                  cpu_except_nfp:
  1465                                  	; 02/04/2015
  1466 000008ED BB[1A060000]            	mov	ebx, hang
  1467 000008F2 875C241C                	xchg	ebx, [esp+28]
  1468                                  		; EIP (points to instruction which faults)
  1469                                  	  	; New EIP (hang)
  1470 000008F6 891D[3C700000]          	mov	[FaultOffset], ebx
  1471 000008FC C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1472 00000904 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1473                                  	;
  1474 0000090C 88C4                    	mov	ah, al
  1475 0000090E 240F                    	and	al, 0Fh
  1476 00000910 3C09                    	cmp	al, 9
  1477 00000912 7602                    	jna	short h1ok
  1478 00000914 0407                    	add	al, 'A'-':'
  1479                                  h1ok:
  1480 00000916 D0EC                    	shr	ah, 1
  1481 00000918 D0EC                    	shr	ah, 1
  1482 0000091A D0EC                    	shr	ah, 1
  1483 0000091C D0EC                    	shr	ah, 1
  1484 0000091E 80FC09                  	cmp	ah, 9
  1485 00000921 7603                    	jna	short h2ok
  1486 00000923 80C407                  	add	ah, 'A'-':'
  1487                                  h2ok:	
  1488 00000926 86E0                    	xchg 	ah, al	
  1489 00000928 66053030                	add	ax, '00'
  1490 0000092C 66A3[666B0000]          	mov	[excnstr], ax
  1491                                  	;
  1492                                  	; 29/08/2014
  1493 00000932 A1[3C700000]            	mov	eax, [FaultOffset]
  1494 00000937 51                      	push	ecx
  1495 00000938 52                      	push	edx
  1496 00000939 89E3                    	mov	ebx, esp
  1497                                  	; 28/08/2015
  1498 0000093B B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1499                                  			  ; to hexadecimal string
  1500                                  	;mov	ecx, 10	    ; divisor to convert
  1501                                  			    ; binary number to decimal string
  1502                                  b2d1:
  1503 00000940 31D2                    	xor	edx, edx
  1504 00000942 F7F1                    	div	ecx
  1505                                  	;push	dx
  1506                                  	; 02/01/2022
  1507 00000944 52                      	push	edx
  1508 00000945 39C8                    	cmp	eax, ecx
  1509 00000947 73F7                    	jnb	short b2d1
  1510 00000949 BF[716B0000]            	mov	edi, EIPstr ; EIP value
  1511                                  			    ; points to instruction which faults
  1512                                  	; 28/08/2015
  1513 0000094E 89C2                    	mov	edx, eax
  1514                                  b2d2:
  1515                                  	;add	al, '0'
  1516 00000950 8A82[F6160000]          	mov	al, [edx+hexchrs]
  1517 00000956 AA                      	stosb		    ; write hexadecimal digit to its place
  1518 00000957 39E3                    	cmp	ebx, esp
  1519 00000959 7605                    	jna	short b2d3
  1520                                  	; 02/01/2022
  1521 0000095B 58                      	pop	eax
  1522                                  	;pop	ax
  1523 0000095C 88C2                    	mov	dl, al
  1524 0000095E EBF0                    	jmp	short b2d2
  1525                                  b2d3:
  1526 00000960 B068                    	mov 	al, 'h' ; 28/08/2015
  1527 00000962 AA                      	stosb
  1528 00000963 B020                    	mov	al, 20h	    ; space
  1529 00000965 AA                      	stosb
  1530 00000966 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1531 00000968 AA                      	stosb
  1532                                  	;
  1533 00000969 5A                      	pop	edx
  1534 0000096A 59                      	pop	ecx
  1535                                  	;
  1536 0000096B B44F                    	mov	ah, 4Fh	; red (4) background, 
  1537                                  			; white (F) forecolor
  1538 0000096D BE[566B0000]            	mov	esi, exc_msg ; message offset
  1539                                  	;
  1540 00000972 EB11                    	jmp	short piemsg
  1541                                  	;
  1542                                          ;add    dword [scr_row], 0A0h
  1543                                          ;mov    edi, [scr_row]
  1544                                          ;
  1545                                  	;call 	printk
  1546                                  	;
  1547                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1548                                  	;out	20h, al	; 8259 PORT
  1549                                  	;
  1550                                  	;pop	es
  1551                                  	;pop	ds
  1552                                  	;pop	edi
  1553                                  	;pop	esi
  1554                                  	;pop 	eax
  1555                                  	;iret
  1556                                  	
  1557                                  	; 28/08/2015
  1558                                  	; 23/02/2015
  1559                                  	; 20/08/2014
  1560                                  ignore_int:
  1561 00000974 50                      	push	eax
  1562 00000975 53                      	push	ebx ; 23/02/2015
  1563 00000976 56                      	push	esi
  1564 00000977 57                      	push	edi
  1565 00000978 1E                      	push 	ds
  1566 00000979 06                      	push 	es
  1567                                  	; 28/08/2015
  1568 0000097A 0F20D8                  	mov	eax, cr3
  1569 0000097D 50                      	push	eax ; (*) page directory
  1570                                  	;
  1571 0000097E B467                    	mov	ah, 67h	; brown (6) background, 
  1572                                  			; light gray (7) forecolor
  1573 00000980 BE[146B0000]            	mov	esi, int_msg ; message offset
  1574                                  piemsg:
  1575                                          ; 27/08/2014
  1576 00000985 8105[D86A0000]A000-             add     dword [scr_row], 0A0h
  1576 0000098D 0000               
  1577 0000098F 8B3D[D86A0000]                  mov     edi, [scr_row]
  1578                                          ;
  1579 00000995 E8BAFCFFFF              	call 	printk
  1580                                  	;
  1581                                  	; 23/02/2015
  1582 0000099A B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1583 0000099C E6A0                    	out	0A0h, al ; the 2nd 8259
  1584                                  iiretp: ; 01/09/2015
  1585                                  	; 28/08/2015
  1586 0000099E 58                      	pop	eax ; (*) page directory
  1587 0000099F 0F22D8                  	mov	cr3, eax
  1588                                  	;
  1589                                  iiret:
  1590                                  	; 22/08/2014
  1591 000009A2 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1592 000009A4 E620                    	out	20h, al	; 8259 PORT
  1593                                  	;
  1594 000009A6 07                      	pop	es
  1595 000009A7 1F                      	pop	ds
  1596 000009A8 5F                      	pop	edi
  1597 000009A9 5E                      	pop	esi
  1598 000009AA 5B                      	pop	ebx ; 29/08/2014
  1599 000009AB 58                      	pop 	eax
  1600 000009AC CF                      	iretd
  1601                                  
  1602                                  	; 26/02/2015
  1603                                  	; 07/09/2014
  1604                                  	; 25/08/2014
  1605                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1606                                  	; 22/08/2014
  1607 000009AD 50                      	push	eax
  1608 000009AE 53                      	push	ebx ; 29/08/2014
  1609 000009AF 56                      	push	esi
  1610 000009B0 57                      	push	edi
  1611 000009B1 1E                      	push 	ds
  1612 000009B2 06                      	push 	es
  1613                                  	;
  1614 000009B3 B810000000              	mov	eax, KDATA
  1615 000009B8 8ED8                    	mov	ds, ax
  1616 000009BA 8EC0                    	mov	es, ax
  1617                                  	;
  1618                                  	; 25/08/2014
  1619 000009BC E884000000              	call	rtc_p
  1620                                  	;
  1621                                  	; 22/02/2015 - dsectpm.s
  1622                                  	; [ source: http://wiki.osdev.org/RTC ]
  1623                                  	; read status register C to complete procedure
  1624                                  	;(it is needed to get a next IRQ 8) 
  1625 000009C1 B00C                    	mov	al, 0Ch ; 
  1626 000009C3 E670                    	out	70h, al ; select register C
  1627 000009C5 90                      	nop
  1628 000009C6 E471                    	in	al, 71h ; just throw away contents
  1629                                  	; 22/02/2015
  1630 000009C8 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1631 000009CA E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1632                                  	;
  1633 000009CC EBD4                    	jmp	short iiret	
  1634                                  
  1635                                  	; 22/08/2014
  1636                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1637                                  	; (INT 1Ah)
  1638                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1639                                  time_of_day:
  1640 000009CE E85F010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1641 000009D3 726F                            jc      short rtc_retn 
  1642 000009D5 B000                    	mov	al, CMOS_SECONDS
  1643 000009D7 E840010000              	call	CMOS_READ
  1644 000009DC A2[FC6F0000]            	mov	[time_seconds], al 
  1645 000009E1 B002                    	mov	al, CMOS_MINUTES
  1646 000009E3 E834010000              	call	CMOS_READ
  1647 000009E8 A2[FD6F0000]            	mov	[time_minutes], al 
  1648 000009ED B004                    	mov	al, CMOS_HOURS
  1649 000009EF E828010000              	call	CMOS_READ
  1650 000009F4 A2[FE6F0000]                    mov     [time_hours], al
  1651 000009F9 B006                    	mov	al, CMOS_DAY_WEEK 
  1652 000009FB E81C010000              	call	CMOS_READ
  1653 00000A00 A2[FF6F0000]            	mov	[date_wday], al
  1654 00000A05 B007                     	mov	al, CMOS_DAY_MONTH
  1655 00000A07 E810010000              	call	CMOS_READ
  1656 00000A0C A2[00700000]            	mov	[date_day], al
  1657 00000A11 B008                    	mov	al, CMOS_MONTH
  1658 00000A13 E804010000              	call	CMOS_READ
  1659 00000A18 A2[01700000]            	mov	[date_month], al
  1660 00000A1D B009                    	mov	al, CMOS_YEAR
  1661 00000A1F E8F8000000              	call	CMOS_READ
  1662 00000A24 A2[02700000]            	mov	[date_year], al
  1663 00000A29 B032                    	mov	al, CMOS_CENTURY
  1664 00000A2B E8EC000000              	call	CMOS_READ
  1665 00000A30 A2[03700000]            	mov	[date_century], al
  1666                                  	;
  1667 00000A35 B000                    	mov	al, CMOS_SECONDS
  1668 00000A37 E8E0000000              	call 	CMOS_READ
  1669 00000A3C 3A05[FC6F0000]          	cmp	al, [time_seconds]
  1670 00000A42 758A                    	jne	short time_of_day
  1671                                  
  1672                                  rtc_retn:
  1673 00000A44 C3                      	retn
  1674                                  
  1675                                  rtc_p:
  1676                                  	; 27/12/2021 (Retro UNIX 386 v1.2)
  1677                                  	; 07/09/2014
  1678                                  	; 29/08/2014
  1679                                  	; 27/08/2014
  1680                                  	; 25/08/2014
  1681                                   	; Print Real Time Clock content
  1682                                  	;
  1683                                  	;
  1684 00000A45 E884FFFFFF              	call	time_of_day
  1685 00000A4A 72F8                    	jc	short rtc_retn
  1686                                  	;
  1687 00000A4C 3A05[C86B0000]          	cmp	al, [ptime_seconds]
  1688 00000A52 74F0                            je      short rtc_retn ; 29/08/2014
  1689                                  	;
  1690 00000A54 A2[C86B0000]            	mov	[ptime_seconds], al
  1691                                  	;
  1692 00000A59 A0[03700000]            	mov	al, [date_century]
  1693 00000A5E E8EA000000              	call	bcd_to_ascii
  1694 00000A63 66A3[956B0000]          	mov	[datestr+6], ax
  1695 00000A69 A0[02700000]            	mov	al, [date_year]
  1696 00000A6E E8DA000000              	call	bcd_to_ascii
  1697 00000A73 66A3[976B0000]          	mov	[datestr+8], ax
  1698 00000A79 A0[01700000]            	mov	al, [date_month]
  1699 00000A7E E8CA000000              	call	bcd_to_ascii
  1700 00000A83 66A3[926B0000]          	mov	[datestr+3], ax
  1701 00000A89 A0[00700000]            	mov	al, [date_day]
  1702 00000A8E E8BA000000              	call	bcd_to_ascii
  1703 00000A93 66A3[8F6B0000]          	mov	[datestr], ax
  1704                                  	;
  1705 00000A99 0FB61D[FF6F0000]        	movzx	ebx, byte [date_wday]
  1706 00000AA0 C0E302                  	shl 	bl, 2
  1707 00000AA3 81C3[A86B0000]          	add	ebx, daytmp
  1708 00000AA9 8B03                    	mov	eax, [ebx]
  1709 00000AAB A3[9A6B0000]            	mov	[daystr], eax
  1710                                  	;
  1711 00000AB0 A0[FE6F0000]            	mov	al, [time_hours]
  1712 00000AB5 E893000000              	call	bcd_to_ascii
  1713 00000ABA 66A3[9E6B0000]          	mov	[timestr], ax
  1714 00000AC0 A0[FD6F0000]            	mov	al, [time_minutes]
  1715 00000AC5 E883000000              	call	bcd_to_ascii
  1716 00000ACA 66A3[A16B0000]          	mov	[timestr+3], ax
  1717 00000AD0 A0[FC6F0000]            	mov	al, [time_seconds]
  1718 00000AD5 E873000000              	call	bcd_to_ascii
  1719 00000ADA 66A3[A46B0000]          	mov	[timestr+6], ax
  1720                                  	;		
  1721 00000AE0 BE[7D6B0000]            	mov	esi, rtc_msg ; message offset
  1722                                  	; 23/02/2015
  1723 00000AE5 52                      	push	edx
  1724 00000AE6 51                      	push	ecx
  1725                                  	; 07/09/2014
  1726                                  	;mov	bx, 2	; Video page 2
  1727                                  	; 27/12/2021
  1728 00000AE7 29DB                    	sub	ebx, ebx
  1729                                  	;mov	bl, 2
  1730                                  	; 15/02/2022
  1731 00000AE9 B307                    	mov	bl, 7	; Video page 7
  1732                                  prtmsg:
  1733 00000AEB AC                      	lodsb
  1734 00000AEC 08C0                    	or	al, al
  1735 00000AEE 740D                    	jz	short prtmsg_ok
  1736 00000AF0 56                      	push	esi
  1737                                  	;push	bx
  1738 00000AF1 53                              push	ebx ; 27/12/2021
  1739 00000AF2 B43F                    	mov	ah, 3Fh	; cyan (6) background, 
  1740                                  			; white (F) forecolor
  1741 00000AF4 E8C1080000              	call 	write_tty
  1742                                  	;pop	bx
  1743 00000AF9 5B                      	pop	ebx ; 27/12/2021
  1744 00000AFA 5E                      	pop	esi
  1745 00000AFB EBEE                    	jmp	short prtmsg
  1746                                  	;
  1747                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1748                                  	;call	printk
  1749                                  prtmsg_ok:
  1750                                  	; 07/09/2014
  1751                                  	;xor	dx, dx		; column 0, row 0
  1752                                  	; 27/12/2021
  1753 00000AFD 31D2                    	xor	edx, edx
  1754 00000AFF E8C0090000              	call	set_cpos	; set curspor position to 0,0 
  1755                                  	; 23/02/2015
  1756 00000B04 59                      	pop	ecx
  1757 00000B05 5A                      	pop	edx
  1758 00000B06 C3                      	retn
  1759                                  
  1760                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1761                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1762                                  default_irq7:
  1763                                  	; 04/12/2021
  1764                                  	;push	ax
  1765 00000B07 50                      	push	eax
  1766 00000B08 B00B                    	mov	al, 0Bh  ; In-Service register
  1767 00000B0A E620                    	out	20h, al
  1768 00000B0C EB00                            jmp short $+2
  1769 00000B0E EB00                    	jmp short $+2
  1770 00000B10 E420                    	in	al, 20h
  1771 00000B12 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1772 00000B14 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1773 00000B16 B020                            mov     al, 20h ; EOI
  1774 00000B18 E620                    	out	20h, al 
  1775                                  irq7_iret:
  1776                                  	;pop	ax
  1777                                  	; 04/12/2021
  1778 00000B1A 58                      	pop	eax
  1779 00000B1B CF                      	iretd
  1780                                  	
  1781                                  	; 04/12/2021
  1782                                  	; 22/08/2014
  1783                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1784                                  CMOS_READ:
  1785 00000B1C 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1786 00000B1D D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1787 00000B1F F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1788 00000B20 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1789 00000B22 FA                      	cli		; DISABLE INTERRUPTS
  1790 00000B23 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1791 00000B25 90                      	nop		; I/O DELAY
  1792 00000B26 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1793                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1794                                  	; 04/12/2021
  1795 00000B28 50                      	push	eax
  1796                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1797                                  		     ; ----- 10/06/85 (test4.asm)
  1798 00000B29 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1799                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1800 00000B2B D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1801 00000B2D E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1802                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1803                                  	; 04/12/2021
  1804 00000B2F 58                      	pop	eax
  1805 00000B30 9D                      	popf	
  1806 00000B31 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1807                                  
  1808                                  	; 22/08/2014
  1809                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1810                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1811 00000B32 51                      	push	ecx
  1812 00000B33 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1813                                  		; mov cx, 800	
  1814                                  UPD_10:
  1815 00000B38 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1816 00000B3A FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1817 00000B3B E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1818 00000B40 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1819 00000B42 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1820 00000B44 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1821 00000B45 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1822 00000B47 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1823                                  		; xor ax, ax
  1824 00000B49 F9                      	stc				; SET CARRY FOR ERROR
  1825                                  UPD_90:
  1826 00000B4A 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1827 00000B4B FA                      	cli				; INTERRUPTS OFF DURING SET
  1828 00000B4C C3                      	retn				; RETURN WITH CY FLAG SET
  1829                                  
  1830                                  bcd_to_ascii:
  1831                                  	; 25/08/2014
  1832                                  	; INPUT ->
  1833                                  	;	al = Packed BCD number
  1834                                  	; OUTPUT ->
  1835                                  	;	ax  = ASCII word/number
  1836                                  	;
  1837                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1838                                  	;
  1839 00000B4D D410                    	db	0D4h, 10h		; Undocumented inst. AAM
  1840                                  					; AH = AL / 10h
  1841                                  					; AL = AL MOD 10h
  1842 00000B4F 660D3030                	or	ax, '00'		; Make it ASCII based
  1843                                  
  1844 00000B53 86E0                            xchg	ah, al 
  1845                                  	
  1846 00000B55 C3                      	retn	
  1847                                  	
  1848                                  
  1849                                  %include 'keyboard.s' ; 07/03/2015
  1850                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1851                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1852                              <1> ; ****************************************************************************
  1853                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1854                              <1> ; Last Modification: 05/12/2021
  1855                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1856                              <1> ;
  1857                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1858                              <1> 
  1859                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  1860                              <1> ; 30/06/2015
  1861                              <1> ; 11/03/2015
  1862                              <1> ; 28/02/2015
  1863                              <1> ; 25/02/2015
  1864                              <1> ; 20/02/2015
  1865                              <1> ; 18/02/2015
  1866                              <1> ; 03/12/2014
  1867                              <1> ; 07/09/2014
  1868                              <1> ; KEYBOARD INTERRUPT HANDLER
  1869                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1870                              <1> 
  1871                              <1> ;getch:
  1872                              <1> ;	; 18/02/2015
  1873                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1874                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1875                              <1> ;	; routine, later... (multi tasking ability)
  1876                              <1> ;	; 28/02/2015
  1877                              <1> ;	sti	; enable interrupts
  1878                              <1> ;	;
  1879                              <1> ;	;push	esi
  1880                              <1> ;	;push	ebx
  1881                              <1> ;	;xor	ebx, ebx
  1882                              <1> ;	;mov	bl, [ptty]  ; active_page
  1883                              <1> ;	;mov	esi, ebx
  1884                              <1> ;	;shl 	si, 1
  1885                              <1> ;	;add	esi, ttychr
  1886                              <1> ;getch_1:
  1887                              <1> ;	;mov	ax, [esi]
  1888                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1889                              <1> ;	and	ax, ax
  1890                              <1> ;	jz	short getch_2
  1891                              <1> ;	mov	word [ttychr], 0
  1892                              <1> ;	;mov	word [esi], 0
  1893                              <1> ;	;pop	ebx
  1894                              <1> ;	;pop	esi
  1895                              <1> ;	retn
  1896                              <1> ;getch_2:
  1897                              <1> ;	hlt	; not proper for multi tasking!
  1898                              <1> ;		; (temporary halt for now)
  1899                              <1> ;		; 'sleep' on tty 
  1900                              <1> ;		; will (must) be located here		
  1901                              <1> ;	nop
  1902                              <1> ;	jmp	short getch_1
  1903                              <1> 
  1904                              <1> keyb_int:
  1905                              <1> 	; 30/06/2015
  1906                              <1> 	; 25/02/2015
  1907                              <1> 	; 20/02/2015
  1908                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1909                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1910                              <1> 	; 30/06/2014
  1911                              <1> 	; 10/05/2013	
  1912                              <1>       	; Retro Unix 8086 v1 feature only!
  1913                              <1> 	; 03/03/2014
  1914                              <1> 	
  1915 00000B56 1E                  <1> 	push	ds
  1916 00000B57 53                  <1> 	push	ebx
  1917 00000B58 50                  <1> 	push	eax
  1918                              <1> 	;
  1919 00000B59 66B81000            <1> 	mov	ax, KDATA
  1920 00000B5D 8ED8                <1> 	mov	ds, ax
  1921                              <1> 	;
  1922 00000B5F 9C                  <1> 	pushfd
  1923 00000B60 0E                  <1> 	push	cs
  1924 00000B61 E812020000          <1> 	call	kb_int  ; int_09h
  1925                              <1> 	;
  1926 00000B66 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1927                              <1> 	;call	getc
  1928 00000B68 E856000000          <1> 	call	int_16h ; 30/06/2015
  1929 00000B6D 7450                <1> 	jz	short keyb_int4
  1930                              <1> 	;
  1931 00000B6F B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1932                              <1> 	;call	getc
  1933 00000B71 E84D000000          <1> 	call	int_16h ; 30/06/2015
  1934                              <1> 	;
  1935                              <1> 	; 20/02/2015
  1936 00000B76 0FB61D[B66F0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1937                              <1> 	;
  1938 00000B7D 20C0                <1> 	and 	al, al
  1939 00000B7F 751E                <1> 	jnz	short keyb_int1
  1940                              <1> 	;
  1941 00000B81 80FC68              <1> 	cmp	ah, 68h	; ALT + F1 key
  1942 00000B84 7219                <1> 	jb	short keyb_int1
  1943 00000B86 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1944 00000B89 7714                <1> 	ja	short keyb_int1
  1945                              <1> 	;
  1946 00000B8B 88D8                <1> 	mov	al, bl
  1947 00000B8D 0468                <1> 	add	al, 68h
  1948 00000B8F 38E0                <1> 	cmp	al, ah
  1949 00000B91 7409                <1> 	je	short keyb_int0
  1950 00000B93 88E0                <1> 	mov	al, ah
  1951 00000B95 2C68                <1> 	sub	al, 68h
  1952 00000B97 E83D0A0000          <1> 	call	tty_sw
  1953                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1954                              <1> keyb_int0: ; 30/06/2015
  1955 00000B9C 6631C0              <1> 	xor	ax, ax
  1956                              <1> keyb_int1:
  1957 00000B9F D0E3                <1> 	shl	bl, 1
  1958 00000BA1 81C3[B86F0000]      <1> 	add	ebx, ttychr
  1959                              <1> 	;
  1960 00000BA7 6609C0              <1> 	or	ax, ax
  1961 00000BAA 7406                <1> 	jz	short keyb_int2
  1962                              <1> 	;
  1963 00000BAC 66833B00            <1> 	cmp 	word [ebx], 0
  1964 00000BB0 7703                <1>         ja      short keyb_int3 
  1965                              <1> keyb_int2:
  1966 00000BB2 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1967                              <1> 			   ; and scan code of the character
  1968                              <1> 			   ; for current tty (or last tty
  1969                              <1> 			   ; just before tty switch).
  1970                              <1> keyb_int3:
  1971 00000BB5 A0[B66F0000]        <1>         mov     al, [ptty]
  1972 00000BBA E80F440000          <1> 	call	wakeup
  1973                              <1> 	;
  1974                              <1> keyb_int4:
  1975 00000BBF 58                  <1> 	pop	eax
  1976 00000BC0 5B                  <1> 	pop	ebx
  1977 00000BC1 1F                  <1> 	pop	ds
  1978 00000BC2 CF                  <1> 	iret
  1979                              <1> 
  1980                              <1> ; 18/02/2015
  1981                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1982                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1983                              <1> ; scancode and ascii code of the character 
  1984                              <1> ; in the tty input (ttychr) buffer. 
  1985                              <1> ; Test procedures must call 'getch' for tty input
  1986                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1987                              <1> ; due to infinite (key press) waiting loop.
  1988                              <1> ; 
  1989                              <1> ; 03/12/2014
  1990                              <1> ; 26/08/2014
  1991                              <1> ; KEYBOARD I/O
  1992                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1993                              <1> 
  1994                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1995                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1996                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1997                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1998                              <1> 
  1999                              <1> int_16h: ; 30/06/2015
  2000                              <1> ;getc:
  2001 00000BC3 9C                  <1> 	pushfd	; 28/08/2014
  2002 00000BC4 0E                  <1> 	push 	cs
  2003 00000BC5 E826000000          <1> 	call 	getc_int
  2004 00000BCA C3                  <1> 	retn
  2005                              <1> 
  2006                              <1> ; 05/12/2021
  2007                              <1> 
  2008                              <1> 	;-----	SHIFT STATUS
  2009                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2010 00000BCB 8A25[B4690000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2011 00000BD1 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2012                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2013                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2014 00000BD4 C0E405              <1>         shl	ah, 5
  2015 00000BD7 A0[B4690000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2016 00000BDC 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2017 00000BDE 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2018 00000BE0 A0[B6690000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2019 00000BE5 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2020 00000BE7 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2021                              <1> _K3:
  2022 00000BE9 A0[B3690000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2023 00000BEE EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2024                              <1> 
  2025                              <1> getc_int:
  2026                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2027                              <1> 	; 28/02/2015
  2028                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2029                              <1> 	;	      instead of pc-at bios - 1985-)
  2030                              <1> 	; 28/08/2014 (_k1d)
  2031                              <1> 	; 30/06/2014
  2032                              <1> 	; 03/03/2014
  2033                              <1> 	; 28/02/2014
  2034                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2035                              <1> 	; rombios source code (21/04/1986)
  2036                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2037                              <1> 	;
  2038                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2039                              <1> 	;
  2040                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2041                              <1> 	; KEYBOARD I/O								      :
  2042                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2043                              <1> 	; INPUT									      :
  2044                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2045                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2046                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2047                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2048                              <1> 	;-----------------------------------------------------------------------------:
  2049                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2050                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2051                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2052                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2053                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2054                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2055                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2056                              <1> 	;-----------------------------------------------------------------------------:	
  2057                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2058                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2059                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2060                              <1> 	;-----------------------------------------------------------------------------:	
  2061                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2062                              <1> 	;	      (AL) = 05H                                                      :
  2063                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2064                              <1> 	;		       							      :
  2065                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2066                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2067                              <1> 	;                     --------------------------------------------            :
  2068                              <1> 	;			00H        30.0        10H        7.5                 :
  2069                              <1> 	;			01H        26.7        11H        6.7                 :
  2070                              <1> 	;			02H        24.0        12H        6.0                 :
  2071                              <1> 	;			03H        21.8        13H        5.5                 :
  2072                              <1> 	;			04H        20.0        14H        5.0                 :
  2073                              <1> 	;			05H        18.5        15H        4.6                 :
  2074                              <1> 	;			06H        17.1        16H        4.3                 :
  2075                              <1> 	;			07H        16.0        17H        4.0                 :
  2076                              <1> 	;			08H        15.0        18H        3.7                 :
  2077                              <1> 	;			09H        13.3        19H        3.3                 :
  2078                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2079                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2080                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2081                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2082                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2083                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2084                              <1> 	;									      :
  2085                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2086                              <1> 	;		       							      :
  2087                              <1> 	;                     REGISTER     DELAY                                      :
  2088                              <1> 	;                      VALUE       VALUE                                      :
  2089                              <1> 	;                     ------------------                                      :
  2090                              <1> 	;			00H        250 ms                                     :
  2091                              <1> 	;			01H        500 ms                                     :
  2092                              <1> 	;			02H        750 ms                                     :
  2093                              <1> 	;			03H       1000 ms                                     :
  2094                              <1> 	;-----------------------------------------------------------------------------:
  2095                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2096                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2097                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2098                              <1> 	;		           (CH) = SCAN CODE                                   :
  2099                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2100                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2101                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2102                              <1> 	;-----------------------------------------------------------------------------:		
  2103                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2104                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2105                              <1> 	;-----------------------------------------------------------------------------:
  2106                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2107                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2108                              <1> 	;-----------------------------------------------------------------------------:	
  2109                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2110                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2111                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2112                              <1> 	; OUTPUT					                              :
  2113                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2114                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2115                              <1> 	;------------------------------------------------------------------------------
  2116                              <1> 	
  2117 00000BF0 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2118 00000BF1 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2119 00000BF2 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2120                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2121 00000BF3 66BB1000            <1>         mov     bx, KDATA 
  2122 00000BF7 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2123 00000BF9 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2124 00000BFB 742D                <1> 	jz	short _K1		; ASCII_READ
  2125 00000BFD FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2126 00000BFF 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2127 00000C01 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2128 00000C03 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2129 00000C05 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2130 00000C07 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2131 00000C09 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2132 00000C0C 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2133                              <1> _KIO1:	
  2134 00000C0E 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2135 00000C11 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2136 00000C13 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2137 00000C15 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2138 00000C17 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2139 00000C19 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2140                              <1> _KIO_EXIT:
  2141                              <1> 	;pop	ecx			; RECOVER REGISTER
  2142 00000C1B 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2143 00000C1C 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2144 00000C1D CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2145                              <1> 
  2146                              <1> 	;-----	ASCII CHARACTER
  2147                              <1> _K1E:	
  2148 00000C1E E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2149 00000C23 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2150 00000C28 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2151                              <1> _K1:	
  2152 00000C2A E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2153 00000C2F E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2154 00000C34 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2155                              <1> _K1A:
  2156 00000C36 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2157                              <1> 
  2158                              <1> 	;-----	ASCII STATUS
  2159                              <1> _K2E:	
  2160 00000C38 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2161 00000C3D 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2162 00000C3F 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2163 00000C40 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2164 00000C45 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2165                              <1> _K2:	
  2166 00000C47 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2167 00000C4C 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2168 00000C4E 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2169 00000C4F E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2170 00000C54 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2171 00000C56 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2172 00000C57 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2173 00000C5C EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2174                              <1> _K2A:
  2175 00000C5E 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2176                              <1> _K2B:
  2177                              <1> 	;pop	ecx			; RECOVER REGISTER
  2178 00000C5F 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2179 00000C60 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2180 00000C61 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2181                              <1> 
  2182                              <1> ; 05/12/2021
  2183                              <1> ;	;-----	SHIFT STATUS
  2184                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2185                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2186                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2187                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2188                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2189                              <1> ;       shl	ah, 5
  2190                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2191                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2192                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2193                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2194                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2195                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2196                              <1> ;_K3:
  2197                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2198                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2199                              <1> 
  2200                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2201                              <1> _K300:
  2202 00000C64 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2203 00000C66 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2204 00000C68 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2205 00000C6B 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2206 00000C6D F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2207 00000C70 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2208 00000C72 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2209 00000C74 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2210                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2211                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2212 00000C79 C0E705              <1> 	shl	bh, 5
  2213 00000C7C 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2214 00000C7E 08F8                <1> 	or	al, bh			; AND DELAY
  2215 00000C80 E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2216 00000C85 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2217                              <1> 
  2218                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2219                              <1> _K500:
  2220 00000C87 56                  <1> 	push	esi			; SAVE SI (esi)
  2221 00000C88 FA                  <1> 	cli				; 
  2222 00000C89 8B1D[C4690000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2223 00000C8F 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2224 00000C91 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2225 00000C96 3B1D[C0690000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2226 00000C9C 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2227 00000C9E 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2228 00000CA1 891D[C4690000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2229 00000CA7 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2230 00000CA9 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2231                              <1> _K502:
  2232 00000CAB B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2233                              <1> _K504:
  2234 00000CAD FB                  <1> 	sti				
  2235 00000CAE 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2236 00000CAF E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2237                              <1> 
  2238                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2239                              <1> _K1S:
  2240 00000CB4 FA                  <1> 	cli	; 03/12/2014
  2241 00000CB5 8B1D[C0690000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2242 00000CBB 3B1D[C4690000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2243                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2244 00000CC1 750F                <1> 	jne	short _k1x ; 03/12/2014
  2245                              <1> 	;
  2246                              <1> 	; 03/12/2014
  2247                              <1> 	; 28/08/2014
  2248                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2249                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2250                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2251                              <1> _K1T:                                   ; ASCII READ
  2252 00000CC3 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2253 00000CC4 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2254                              <1> _K1U:	
  2255 00000CC5 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2256 00000CC6 8B1D[C0690000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2257 00000CCC 3B1D[C4690000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2258                              <1> _k1x:
  2259 00000CD2 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2260 00000CD3 9C                  <1> 	pushf				; SAVE FLAGS
  2261 00000CD4 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2262 00000CD9 8A1D[B5690000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2263 00000CDF 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2264 00000CE1 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2265 00000CE4 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2266 00000CE6 E86E060000          <1> 	call	SND_LED1
  2267 00000CEB FA                  <1> 	cli				; DISABLE INTERRUPTS
  2268                              <1> _K1V:
  2269 00000CEC 9D                  <1> 	popf				; RESTORE FLAGS
  2270 00000CED 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2271 00000CEE 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2272                              <1> 	;
  2273 00000CF0 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2274 00000CF3 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2275 00000CF8 891D[C0690000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2276 00000CFE C3                  <1> 	retn				; RETURN
  2277                              <1> 
  2278                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2279                              <1> _K2S:
  2280 00000CFF FA                  <1> 	cli				; INTERRUPTS OFF
  2281 00000D00 8B1D[C0690000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2282 00000D06 3B1D[C4690000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2283 00000D0C 668B03              <1> 	mov	ax, [ebx]
  2284 00000D0F 9C                  <1> 	pushf				; SAVE FLAGS
  2285                              <1> 	;push	ax			; SAVE CODE
  2286                              <1> 	; 05/12/2021
  2287 00000D10 50                  <1> 	push	eax
  2288 00000D11 E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2289 00000D16 8A1D[B5690000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2290 00000D1C 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2291 00000D1E 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2292 00000D21 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2293 00000D23 E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2294                              <1> _K2T:
  2295                              <1> 	;pop	ax			; RESTORE CODE
  2296                              <1> 	; 05/12/2021
  2297 00000D28 58                  <1> 	pop	eax
  2298 00000D29 9D                  <1> 	popf				; RESTORE FLAGS
  2299 00000D2A FB                  <1> 	sti				; INTERRUPTS BACK ON
  2300 00000D2B C3                  <1> 	retn				; RETURN
  2301                              <1> 
  2302                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2303                              <1> _KIO_E_XLAT:
  2304 00000D2C 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2305 00000D2E 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2306 00000D30 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2307 00000D32 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2308 00000D34 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2309                              <1> _KIO_E_RET:				
  2310 00000D36 C3                  <1> 	retn				; GO BACK
  2311                              <1> 
  2312                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2313                              <1> _KIO_S_XLAT:
  2314 00000D37 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2315 00000D3A 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2316 00000D3C 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2317 00000D3E 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2318 00000D40 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2319 00000D42 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2320 00000D44 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2321                              <1> _kio_ret: ; 03/12/2014
  2322 00000D46 F8                  <1> 	clc
  2323 00000D47 C3                  <1> 	retn
  2324                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2325                              <1> _KIO_S1:				
  2326 00000D48 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2327                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2328 00000D4A C3                  <1> 	retn
  2329                              <1> _KIO_S2:		
  2330 00000D4B 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2331 00000D4E 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2332 00000D50 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2333 00000D52 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2334 00000D54 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2335 00000D56 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2336 00000D58 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2337                              <1> _KIO_S3:
  2338 00000D5A 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2339                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2340 00000D5C 75E8                <1> 	jne	short _kio_ret
  2341 00000D5E 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2342 00000D60 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2343 00000D62 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2344                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2345                              <1> _KIO_USE:
  2346                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2347 00000D64 C3                  <1> 	retn				; RETURN	
  2348                              <1> _KIO_DIS:
  2349 00000D65 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2350 00000D66 C3                  <1> 	retn				; RETURN
  2351                              <1> 
  2352                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2353                              <1> _K4:    
  2354 00000D67 43                  <1> 	inc     ebx
  2355 00000D68 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2356 00000D69 3B1D[BC690000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2357                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2358 00000D6F 7206                <1> 	jb	short _K5
  2359 00000D71 8B1D[B8690000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2360                              <1> _K5:
  2361 00000D77 C3                  <1> 	retn
  2362                              <1> 
  2363                              <1> ; 20/02/2015
  2364                              <1> ; 05/12/2014
  2365                              <1> ; 26/08/2014
  2366                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2367                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2368                              <1> ;
  2369                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2370                              <1> ; rombios source code (06/10/1985)
  2371                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2372                              <1> 
  2373                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2374                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2375                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2376                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2377                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2378                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2379                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2380                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2381                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2382                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2383                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2384                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2385                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2386                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2387                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2388                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2389                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2390                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2391                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2392                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2393                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2394                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2395                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2396                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2397                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2398                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2399                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2400                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2401                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2402                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2403                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2404                              <1> F11_M		equ	87		; F11 KEY MAKE
  2405                              <1> F12_M		equ	88		; F12 KEY MAKE
  2406                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2407                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2408                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2409                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2410                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2411                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2412                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2413                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2414                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2415                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2416                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2417                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2418                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2419                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2420                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2421                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2422                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2423                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2424                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2425                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2426                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2427                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2428                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2429                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2430                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2431                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2432                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2433                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2434                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2435                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2436                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2437                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2438                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2439                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2440                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2441                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2442                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2443                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2444                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2445                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2446                              <1> ;
  2447                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2448                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2449                              <1> INTA00		equ	020h		; 8259 PORT
  2450                              <1> 
  2451                              <1> 
  2452                              <1> kb_int:
  2453                              <1> 
  2454                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2455                              <1> ; 17/10/2015 ('ctrlbrk') 
  2456                              <1> ; 05/12/2014
  2457                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2458                              <1> 	;	      instead of pc-at bios - 1985-)
  2459                              <1> ; 26/08/2014
  2460                              <1> ;
  2461                              <1> ; 03/06/86  KEYBOARD BIOS
  2462                              <1> ;
  2463                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2464                              <1> ;										;
  2465                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2466                              <1> ;										;
  2467                              <1> ;--------------------------------------------------------------------------------
  2468                              <1> 
  2469                              <1> KB_INT_1:
  2470 00000D78 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2471                              <1> 	;push	ebp
  2472 00000D79 50                  <1> 	push	eax
  2473 00000D7A 53                  <1> 	push	ebx
  2474 00000D7B 51                  <1> 	push	ecx
  2475 00000D7C 52                  <1> 	push	edx
  2476 00000D7D 56                  <1> 	push	esi
  2477 00000D7E 57                  <1> 	push	edi
  2478 00000D7F 1E                  <1> 	push	ds
  2479 00000D80 06                  <1> 	push	es
  2480 00000D81 FC                  <1> 	cld				; FORWARD DIRECTION
  2481 00000D82 66B81000            <1> 	mov	ax, KDATA
  2482 00000D86 8ED8                <1> 	mov	ds, ax
  2483 00000D88 8EC0                <1> 	mov	es, ax
  2484                              <1> 	;
  2485                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2486 00000D8A B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2487 00000D8C E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2488 00000D91 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2489 00000D92 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2490                              <1> KB_INT_01:
  2491 00000D97 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2492 00000D99 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2493 00000D9B E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2494                              <1> 	;
  2495                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2496 00000D9D E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2497                              <1> 	;
  2498                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2499                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2500                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2501                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2502                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2503                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2504                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2505                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2506                              <1> 	;
  2507                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2508                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2509 00000D9F FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2510 00000DA0 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2511 00000DA2 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2512                              <1> 	;
  2513                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2514 00000DA4 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2515 00000DA6 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2516                              <1> 	;
  2517                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2518 00000DA8 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2519 00000DA9 800D[B5690000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2520 00000DB0 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2521                              <1> 	;
  2522                              <1> 	;-----	RESEND THE LAST BYTE
  2523                              <1> KB_INT_4:
  2524 00000DB5 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2525 00000DB6 800D[B5690000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2526 00000DBD E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2527                              <1> 	;
  2528                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2529                              <1> KB_INT_2:
  2530                              <1> 	;push 	ax			; SAVE DATA IN
  2531                              <1> 	; 05/12/2021
  2532 00000DC2 50                  <1> 	push	eax
  2533 00000DC3 E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2534 00000DC8 8A1D[B5690000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2535 00000DCE 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2536 00000DD0 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2537 00000DD3 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2538 00000DD5 E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2539                              <1> UP0:
  2540                              <1> 	;pop	ax			; RESTORE DATA IN
  2541                              <1> 	; 05/12/2021
  2542 00000DDA 58                  <1> 	pop	eax
  2543                              <1> ;------------------------------------------------------------------------
  2544                              <1> ;	START OF KEY PROCESSING						;
  2545                              <1> ;------------------------------------------------------------------------
  2546 00000DDB 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2547                              <1> 	;
  2548                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2549 00000DDD 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2550                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2551                              <1> 	; 05/12/2021
  2552 00000DDF 7505                <1> 	jne	short K16
  2553 00000DE1 E9ED040000          <1> 	jmp	K62
  2554                              <1> K16:	
  2555 00000DE6 8A3D[B6690000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2556                              <1> 	;
  2557                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2558 00000DEC F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2559 00000DEF 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2560 00000DF1 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2561 00000DF3 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2562 00000DF5 7507                <1> 	jne	short RST_RD_ID
  2563 00000DF7 800D[B6690000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2564                              <1> RST_RD_ID:
  2565 00000DFE 8025[B6690000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2566 00000E05 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2567                              <1> 	; 05/12/2021
  2568                              <1> 	;jmp	K26
  2569                              <1> 	;
  2570                              <1> TST_ID_2:
  2571 00000E07 8025[B6690000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2572 00000E0E 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2573 00000E10 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2574 00000E12 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2575 00000E14 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2576                              <1> 	; 05/12/2021
  2577                              <1> 	;jne	K26
  2578                              <1> 	;
  2579                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2580 00000E16 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2581 00000E19 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2582 00000E1B 800D[B3690000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2583 00000E22 E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2584                              <1> KX_BIT:
  2585 00000E27 800D[B6690000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2586 00000E2E E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2587                              <1> 	;
  2588                              <1> NOT_ID:
  2589 00000E33 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2590 00000E35 750E                <1> 	jne	short TEST_E1
  2591 00000E37 800D[B6690000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2592 00000E3E EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2593                              <1> 	; 05/12/2021
  2594 00000E40 E9DA010000          <1> 	jmp	K26A	
  2595                              <1> TEST_E1:	
  2596 00000E45 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2597 00000E47 750C                <1> 	jne	short NOT_HC
  2598 00000E49 800D[B6690000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2599 00000E50 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2600                              <1> 	;
  2601                              <1> NOT_HC:
  2602 00000E55 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2603 00000E57 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2604 00000E5A 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2605                              <1> 	;
  2606 00000E5C BF[9E680000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2607 00000E61 AE                  <1> 	scasb
  2608                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2609                              <1> 	; 05/12/2021
  2610 00000E62 7458                <1> 	je	short K16B
  2611 00000E64 AE                  <1> 	scasb
  2612 00000E65 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2613 00000E67 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2614                              <1> 	; 05/12/2021
  2615                              <1> 	;jmp	K26
  2616                              <1> 	;
  2617                              <1> NOT_LC_E0:
  2618 00000E69 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2619 00000E6C 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2620 00000E6E B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2621 00000E73 BF[9C680000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2622 00000E78 F2AE                <1> 	repne	scasb			; CHECK IT
  2623 00000E7A 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2624                              <1> 	; 05/12/2021
  2625                              <1> 	;je	K26A			
  2626                              <1> 	;
  2627 00000E7C 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2628 00000E7E 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2629                              <1> 	; 05/12/2021
  2630                              <1> 	;jne	K26
  2631 00000E80 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2632 00000E83 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2633                              <1> 	; 05/12/2021
  2634                              <1> 	;jnz	K26
  2635                              <1>         ; 20/02/2015 
  2636 00000E85 F605[B4690000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2637 00000E8C 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2638                              <1> 	; 05/12/2021
  2639                              <1> 	;jnz	K26
  2640 00000E8E E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2641                              <1> 	;
  2642                              <1> 	;-----	TEST FOR SYSTEM KEY
  2643                              <1> T_SYS_KEY:
  2644 00000E93 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2645 00000E95 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2646                              <1> 	;
  2647 00000E97 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2648 00000E9A 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2649                              <1> 	;
  2650 00000E9C F605[B4690000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2651 00000EA3 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2652                              <1> 	;jnz	K26			
  2653                              <1> 	;
  2654 00000EA5 800D[B4690000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2655 00000EAC B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2656 00000EAE E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2657                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2658 00000EB0 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2659 00000EB2 E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2660                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2661                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2662                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2663                              <1> 	;INT	15H			; USER INTERRUPT	
  2664 00000EB7 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2665                              <1> 	;
  2666 00000EBC E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2667                              <1> 	;
  2668                              <1> K16C:
  2669 00000EC1 8025[B4690000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2670 00000EC8 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2671 00000ECA E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2672                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2673                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2674                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2675                              <1> 	;
  2676                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2677                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2678                              <1> 	;INT	15H			; USER INTERRUPT
  2679                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2680                              <1> 	;
  2681 00000ECC E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2682                              <1> 	;
  2683                              <1> 	;-----	TEST FOR SHIFT KEYS
  2684                              <1> K16A:
  2685 00000ED1 8A1D[B3690000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2686 00000ED7 BF[98680000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2687 00000EDC B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2688 00000EE1 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2689 00000EE3 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2690                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2691                              <1> 	; 05/12/2021
  2692 00000EE5 7405                <1> 	je	short K17
  2693 00000EE7 E914010000          <1> 	jmp	K25
  2694                              <1> 	;
  2695                              <1> 	;------	SHIFT KEY FOUND
  2696                              <1> K17:
  2697 00000EEC 81EF[99680000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2698 00000EF2 8AA7[A0680000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2699 00000EF8 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2700 00000EFA A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2701                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2702                              <1> 	; 05/12/2021
  2703 00000EFC 7405                <1> 	jz	short K17C
  2704 00000EFE E999000000          <1> 	jmp	K23
  2705                              <1> 	;
  2706                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2707                              <1> K17C:
  2708 00000F03 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2709 00000F06 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2710                              <1> 	;
  2711                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2712 00000F08 0825[B3690000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2713 00000F0E A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2714 00000F10 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2715                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2716                              <1> 	; 05/12/2021
  2717 00000F12 E901010000          <1> 	jmp	K26
  2718                              <1> K17D:
  2719 00000F17 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2720 00000F1A 740B                <1> 	jz 	short K17E		; NO, JUMP
  2721 00000F1C 0825[B6690000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2722 00000F22 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2723                              <1> K17E:
  2724 00000F27 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2725 00000F29 0825[B4690000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2726 00000F2F E9E4000000          <1> 	jmp	K26
  2727                              <1> 	;
  2728                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2729                              <1> K18:					; SHIFT-TOGGLE
  2730 00000F34 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2731 00000F37 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2732                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2733                              <1> 	; 05/12/2021
  2734 00000F39 E9C2000000          <1> 	jmp	K25
  2735                              <1> K18A:
  2736 00000F3E 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2737 00000F40 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2738 00000F42 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2739 00000F45 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2740                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2741                              <1> 	; 05/12/2021
  2742 00000F47 E9B4000000          <1> 	jmp	K25
  2743                              <1> K18B:
  2744 00000F4C F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2745 00000F4F 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2746                              <1> K19:	
  2747 00000F51 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2748 00000F54 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2749 00000F56 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2750 00000F59 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2751                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2752 00000F5B 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2753 00000F5D E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2754                              <1> K21:					; MIGHT BE NUMERIC
  2755 00000F62 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2756 00000F65 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2757                              <1> 	;
  2758                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2759 00000F67 8425[B4690000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2760                              <1> 	;jnz	K26
  2761                              <1> 	; 05/12/2021
  2762 00000F6D 7405                <1> 	jz	short K22A
  2763 00000F6F E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2764                              <1> K22A:
  2765 00000F74 0825[B4690000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2766 00000F7A 3025[B3690000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2767                              <1> 	;
  2768                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2769 00000F80 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2770 00000F83 7407                <1> 	jz	short K22B		; GO IF NOT
  2771                              <1> 	;
  2772                              <1> 	; 05/12/2021
  2773                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2774 00000F85 50                  <1> 	push	eax
  2775 00000F86 E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2776                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2777 00000F8B 58                  <1> 	pop	eax
  2778                              <1> K22B:
  2779 00000F8C 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2780                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2781                              <1> 	; 05/12/2021
  2782 00000F8E 7405                <1> 	je	short K22C
  2783 00000F90 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2784                              <1> K22C:
  2785 00000F95 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2786 00000F97 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2787                              <1> 	;
  2788                              <1> 	;-----	BREAK SHIFT FOUND
  2789                              <1> K23:					; BREAK-SHIFT-FOUND
  2790 00000F9C 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2791 00000F9F F6D4                <1> 	not	ah			; INVERT MASK
  2792 00000FA1 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2793 00000FA3 2025[B3690000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2794 00000FA9 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2795 00000FAC 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2796                              <1> 	;
  2797 00000FAE F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2798 00000FB1 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2799 00000FB3 2025[B6690000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2800 00000FB9 EB08                <1> 	jmp	short K23B		; CONTINUE
  2801                              <1> K23A:
  2802 00000FBB D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2803 00000FBD 2025[B4690000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2804                              <1> K23B:
  2805 00000FC3 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2806 00000FC5 A0[B6690000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2807 00000FCA D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2808 00000FCC 0A05[B4690000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2809 00000FD2 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2810 00000FD4 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2811 00000FD6 0805[B3690000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2812 00000FDC 88E0                <1> 	mov	al, ah
  2813                              <1> K23D:
  2814 00000FDE 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2815 00000FE0 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2816                              <1> 	;	
  2817                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2818 00000FE2 A0[B7690000]        <1> 	mov	al, [ALT_INPUT]
  2819 00000FE7 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2820 00000FE9 8825[B7690000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2821 00000FEF 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2822 00000FF1 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2823 00000FF3 E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2824                              <1> 	;
  2825                              <1> K24:					; BREAK-TOGGLE
  2826 00000FF8 2025[B4690000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2827 00000FFE EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2828                              <1> 	;
  2829                              <1> 	;-----	TEST FOR HOLD STATE
  2830                              <1> 					; AL, AH = SCAN CODE
  2831                              <1> K25:					; NO-SHIFT-FOUND
  2832 00001000 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2833 00001002 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2834 00001004 F605[B4690000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2835 0000100B 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2836 0000100D 3C45                <1> 	cmp	al, NUM_KEY
  2837 0000100F 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2838 00001011 8025[B4690000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2839                              <1> 	;
  2840                              <1> K26:
  2841 00001018 8025[B6690000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2842                              <1> K26A:					; INTERRUPT-RETURN
  2843 0000101F FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2844 00001020 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2845 00001022 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2846                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2847 00001024 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2848 00001026 E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2849                              <1> K27A:
  2850 0000102B FA                  <1> 	cli				; DISABLE INTERRUPTS
  2851 0000102C 07                  <1> 	pop	es			; RESTORE REGISTERS
  2852 0000102D 1F                  <1> 	pop	ds
  2853 0000102E 5F                  <1> 	pop	edi
  2854 0000102F 5E                  <1> 	pop	esi
  2855 00001030 5A                  <1> 	pop	edx
  2856 00001031 59                  <1> 	pop	ecx
  2857 00001032 5B                  <1> 	pop	ebx
  2858 00001033 58                  <1> 	pop	eax
  2859                              <1> 	;pop	ebp
  2860 00001034 CF                  <1> 	iret				; RETURN
  2861                              <1> 
  2862                              <1> 	;-----	NOT IN	HOLD STATE
  2863                              <1> K28:					; NO-HOLD-STATE
  2864 00001035 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2865 00001037 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2866                              <1> 	;
  2867 00001039 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2868 0000103C 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2869                              <1>         ; 05/12/2021
  2870                              <1> 	;jz      K38
  2871                              <1> 	;
  2872 0000103E F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2873 00001041 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2874                              <1> 	; 28/02/2015
  2875 00001043 F605[B4690000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2876 0000104A 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2877                              <1> 	; 05/12/2021
  2878                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2879                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2880 0000104C E9D1000000          <1> K28A:	jmp	K38
  2881                              <1> 	;
  2882                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2883                              <1> K29:					; TEST-RESET
  2884 00001051 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2885 00001054 740B                <1> 	jz	short K31		; NO_RESET
  2886 00001056 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2887 00001058 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2888                              <1> 	;
  2889                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2890                              <1>  	; 26/08/2014
  2891                              <1> cpu_reset:
  2892                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2893                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2894 0000105A B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2895 0000105C E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2896                              <1> khere:
  2897 0000105E F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2898 0000105F EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2899                              <1> 
  2900                              <1> 	;
  2901                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2902                              <1> K31:					; NO-RESET
  2903 00001061 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2904 00001063 7507                <1> 	jne	short K311		; NOT THERE
  2905 00001065 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2906 00001067 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2907                              <1> K311:
  2908 0000106C 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2909 0000106E 7509                <1> 	jne	short K312		; NOT THERE
  2910 00001070 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2911 00001074 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2912                              <1> K312:
  2913 00001079 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2914 0000107B 7471                <1>         je	short K37B              ; GO PROCESS
  2915 0000107D 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2916 0000107F 746D                <1>         je	short K37B              ; GO PROCESS
  2917                              <1> 	;
  2918                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2919                              <1> K32:					; ALT-KEY-PAD
  2920 00001081 BF[74680000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2921 00001086 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2922 0000108B F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2923 0000108D 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2924 0000108F F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2925                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2926                              <1> 	; 05/12/2021
  2927 00001092 751C                <1> 	jnz	short K32B
  2928 00001094 81EF[75680000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2929 0000109A A0[B7690000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2930 0000109F B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2931 000010A1 F6E4                <1> 	mul	ah
  2932 000010A3 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2933 000010A6 A2[B7690000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2934                              <1> K32A:
  2935 000010AB E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2936                              <1> K32B:
  2937                              <1> 	; 05/12/2021
  2938 000010B0 EB6A                <1> 	jmp	K37C
  2939                              <1> 	;
  2940                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2941                              <1> K33:					; NO-ALT-KEYPAD
  2942 000010B2 C605[B7690000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2943 000010B9 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2944 000010BE F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2945 000010C0 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2946                              <1> 	;
  2947                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2948                              <1> K34:					; ALT-TOP-ROW
  2949 000010C2 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2950 000010C4 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2951 000010C6 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2952 000010C8 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2953 000010CA 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2954 000010CD EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2955                              <1> 	;
  2956                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2957                              <1> K35:					; ALT-FUNCTION
  2958 000010CF 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2959 000010D1 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2960 000010D3 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2961 000010D5 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2962 000010D7 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2963 000010DA EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2964                              <1> K35A:
  2965 000010DC F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2966 000010DF 7425                <1> 	jz	short K37		; NO, JUMP
  2967 000010E1 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2968 000010E3 7510                <1>         jne     short K35B              ; NOT THERE
  2969 000010E5 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2970 000010E9 E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2971                              <1> K37B:
  2972 000010EE B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2973 000010F0 E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2974                              <1> K35B:
  2975 000010F5 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2976 000010F7 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2977 000010F9 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2978 000010FB 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2979                              <1>         ; 05/12/2021
  2980                              <1> 	;jne	K26
  2981 000010FD 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2982 00001101 E99C010000          <1> 	jmp	K57			; BUFFER FILL
  2983                              <1> K37:
  2984 00001106 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2985 00001108 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2986 0000110A 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2987                              <1>         ;ja	short K32A		; IF SO, IGNORE
  2988 0000110C 0F8706FFFFFF        <1>         ja      K26
  2989 00001112 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2990                              <1> K37A:
  2991 00001115 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2992 00001117 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2993                              <1> K37C:
  2994 0000111C 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2995 0000111E 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2996 00001120 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2997                              <1> 	;
  2998                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2999                              <1> K38:					; NOT-ALT-SHIFT
  3000                              <1> 					; BL STILL HAS SHIFT FLAGS
  3001 00001122 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3002 00001125 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3003                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3004                              <1> 	; 05/12/2021
  3005 00001127 E9AB000000          <1> 	jmp	K44
  3006                              <1> 	;
  3007                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3008                              <1> 	;-----	TEST FOR BREAK
  3009                              <1> K38A:
  3010 0000112C 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3011 0000112E 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3012 00001130 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3013 00001133 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3014 00001135 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3015 00001138 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3016                              <1> K38B:
  3017 0000113A 8B1D[C0690000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3018 00001140 891D[C4690000]      <1> 	mov	[BUFFER_TAIL], ebx
  3019 00001146 C605[B2690000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3020                              <1> 	;
  3021                              <1> 	;-----	ENABLE KEYBOARD
  3022 0000114D B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3023 0000114F E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3024                              <1> 	;
  3025                              <1> 	; CTRL+BREAK code here !!!
  3026                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3027                              <1> 	; 17/10/2015	
  3028 00001154 E857220000          <1> 	call	ctrlbrk ; control+break subroutine
  3029                              <1> 	;
  3030                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3031                              <1> 	; 05/12/2021
  3032 00001159 29C0                <1> 	sub	eax, eax
  3033 0000115B E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3034                              <1> 	;
  3035                              <1> 	;-----	TEST FOR PAUSE
  3036                              <1> K39:					; NO_BREAK
  3037 00001160 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3038 00001163 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3039 00001165 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3040 00001167 7533                <1> 	jne	short K41		; NO-PAUSE
  3041                              <1> K39P:
  3042 00001169 800D[B4690000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3043                              <1> 	;
  3044                              <1> 	;-----	ENABLE KEYBOARD
  3045 00001170 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3046 00001172 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3047                              <1> K39A:
  3048 00001177 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3049 00001179 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3050                              <1> 	;
  3051                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3052 0000117B 803D[B0690000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3053 00001182 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3054 00001184 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3055 00001188 A0[B1690000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3056 0000118D EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3057                              <1> 	;
  3058                              <1> K40:					; PAUSE-LOOP
  3059 0000118E F605[B4690000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3060 00001195 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3061                              <1> 	;
  3062 00001197 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3063                              <1>         ;
  3064                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3065                              <1> K41:					; NO-PAUSE
  3066 0000119C 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3067 0000119E 7513                <1> 	jne	short K42		; NOT-KEY-55
  3068 000011A0 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3069 000011A3 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3070 000011A5 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3071 000011A8 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3072                              <1> K41A:	
  3073 000011AA 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3074 000011AE E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3075                              <1> 	;
  3076                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3077                              <1> K42:					; NOT-KEY-55
  3078 000011B3 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3079 000011B5 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3080 000011B7 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3081 000011B9 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3082 000011BB F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3083 000011BE 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3084 000011C0 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3085 000011C4 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3086                              <1> K42A:
  3087                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3088 000011C9 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3089                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3090                              <1> 	;;jb	K56 ; 20/02/2015
  3091                              <1> 	;;jmp	K64 ; 20/02/2015
  3092                              <1> K42B:
  3093 000011CB BB[A8680000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3094                              <1> 	;;jmp	K64
  3095                              <1> 	;jb	K56 ;; 20/02/2015	
  3096                              <1> 	; 05/12/2021
  3097 000011D0 7267                <1> 	jb	short K45F
  3098 000011D2 E9B9000000          <1> 	jmp	K64	
  3099                              <1>         ;
  3100                              <1> 	;-----	NOT IN CONTROL SHIFT
  3101                              <1> K44:					; NOT-CTL-SHIFT
  3102 000011D7 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3103 000011D9 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3104 000011DB F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3105 000011DE 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3106 000011E0 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3107 000011E3 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3108 000011E5 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3109                              <1> K44A:
  3110 000011E7 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3111 000011EA 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3112                              <1> 	;
  3113                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3114                              <1> K44B:
  3115 000011EC B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3116 000011EE E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3117 000011F3 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3118 000011F5 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3119                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3120                              <1> 	;PUSH 	BP			; SAVE POINTER
  3121                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3122                              <1> 	;POP	BP			; RESTORE POINTER
  3123 000011F7 8025[B6690000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3124 000011FE E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3125                              <1> 	;
  3126                              <1> 	;-----	HANDLE IN-CORE KEYS
  3127                              <1> K45:					; NOT-PRINT-SCREEN
  3128 00001203 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3129 00001205 7734                <1> 	ja	short K46		; JUMP IF NOT
  3130 00001207 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3131 00001209 7505                <1> 	jne	short K45A		; NO, JUMP
  3132 0000120B F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3133 0000120E 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3134                              <1> K45A:
  3135 00001210 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3136 00001215 BF[7E680000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3137 0000121A F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3138                              <1> 		; 20/02/2015
  3139 0000121C 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3140                              <1> 	;
  3141 0000121E F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3142 00001221 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3143                              <1> K45B:
  3144 00001223 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3145 00001226 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3146                              <1> 					; NO, LOWERCASE
  3147                              <1> K45C:
  3148 00001228 BB[00690000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3149 0000122D EB51                <1> 	jmp	short K56	
  3150                              <1> K45D:					; ALMOST-CAPS-STATE
  3151 0000122F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3152 00001232 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3153                              <1> K45E:
  3154 00001234 BB[58690000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3155 00001239 EB45                <1> K45F:	jmp	short K56
  3156                              <1> 	;
  3157                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3158                              <1> K46:					; NOT IN-CORE AREA
  3159 0000123B 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3160                              <1> 	;ja	short K47		; JUMP IF NOT
  3161                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3162 0000123D 7635                <1> 	jna	short K53		
  3163                              <1> 	;
  3164                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3165                              <1> K47:					; NOT F1 - F10
  3166 0000123F 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3167 00001241 772D                <1> 	ja	short K52		; JUMP IF NOT
  3168                              <1> 	;
  3169                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3170                              <1> K48:
  3171 00001243 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3172 00001245 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3173 00001247 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3174 00001249 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3175 0000124B F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3176 0000124E 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3177                              <1> 	;		
  3178 00001250 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3179 00001253 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3180 00001255 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3181                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3182 00001258 75DA                <1> 	jnz	short K45E
  3183                              <1> 	;
  3184                              <1> 	;-----	BASE CASE FOR KEYPAD
  3185                              <1> K49:					
  3186 0000125A 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3187 0000125C 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3188 0000125E B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3189 00001260 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3190                              <1> K49A:
  3191 00001262 BB[00690000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3192 00001267 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3193                              <1> 	;
  3194                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3195                              <1> K50:					; ALMOST-NUM-STATE
  3196 00001269 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3197 0000126C 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3198 0000126E EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3199                              <1> 	;
  3200                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3201                              <1> K52:					; NOT A NUMPAD KEY
  3202 00001270 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3203                              <1> 	;jne	short K53		; JUMP IF NOT
  3204                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3205 00001272 74AF                <1> 	je	short K45B		
  3206                              <1> 	;
  3207                              <1> 	;-----	MUST BE F11 OR F12 
  3208                              <1> K53:					; F1 - F10 COME HERE, TOO
  3209 00001274 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3210 00001277 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3211                              <1> 		; 20/02/2015 
  3212 00001279 BB[58690000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3213 0000127E EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3214                              <1> 	;
  3215                              <1> 	;-----	TRANSLATE THE CHARACTER
  3216                              <1> K56:					; TRANSLATE-CHAR
  3217 00001280 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3218 00001282 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3219 00001283 F605[B6690000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3220 0000128A 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3221 0000128C B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3222 0000128E EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3223                              <1> 	;
  3224                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3225                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3226 00001290 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3227 00001292 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3228 00001293 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3229 00001295 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3230 00001297 F605[B6690000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3231 0000129E 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3232 000012A0 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3233                              <1> 	;
  3234                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3235                              <1> K57:					; BUFFER_FILL
  3236 000012A2 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3237 000012A4 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3238                              <1> 	; 05/12/2021
  3239                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3240 000012A6 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3241                              <1> 	; 05/12/2021
  3242 000012A9 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3243                              <1> 	;je	K26			; INTERRUPT_RETURN
  3244                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3245 000012AB E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3246                              <1> K61:					; NOT-CAPS-STATE
  3247 000012B0 8B1D[C4690000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3248 000012B6 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3249 000012B8 E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3250 000012BD 3B1D[C0690000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3251 000012C3 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3252 000012C5 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3253 000012C8 891D[C4690000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3254 000012CE E945FDFFFF          <1> 	jmp	K26
  3255                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3256                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3257                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3258                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3259                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3260                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3261                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3262                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3263                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3264                              <1> 	;;jmp   K27                    
  3265                              <1> 	;
  3266                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3267                              <1> K62:
  3268 000012D3 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3269 000012D5 E620                <1> 	out	INTA00, al
  3270 000012D7 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3271 000012DB B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3272 000012DD E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3273 000012E2 E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3274                              <1> 
  3275                              <1> SHIP_IT:
  3276                              <1> 	;---------------------------------------------------------------------------------
  3277                              <1> 	; SHIP_IT
  3278                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3279                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3280                              <1> 	;---------------------------------------------------------------------------------
  3281                              <1> 	;
  3282                              <1> 	;push	ax			; SAVE DATA TO SEND
  3283                              <1> 	; 05/12/2021
  3284 000012E7 50                  <1> 	push	eax
  3285                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3286 000012E8 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3287                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3288 000012E9 B900000100          <1> 	mov	ecx, 10000h			
  3289                              <1> S10:
  3290 000012EE E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3291 000012F0 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3292 000012F2 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3293                              <1> 
  3294                              <1> 	;pop	ax			; GET DATA TO SEND
  3295                              <1> 	; 05/12/2021
  3296 000012F4 58                  <1> 	pop	eax
  3297 000012F5 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3298 000012F7 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3299 000012F8 C3                  <1> 	retn				; RETURN TO CALLER
  3300                              <1> 
  3301                              <1> SND_DATA:
  3302                              <1> 	; ---------------------------------------------------------------------------------
  3303                              <1> 	; SND_DATA
  3304                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3305                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3306                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3307                              <1> 	; ---------------------------------------------------------------------------------
  3308                              <1> 	;
  3309                              <1> 	;push	ax			; SAVE REGISTERS
  3310                              <1> 	;push	bx
  3311                              <1> 	; 05/12/2021
  3312 000012F9 50                  <1> 	push	eax
  3313 000012FA 53                  <1> 	push	ebx
  3314 000012FB 51                  <1> 	push	ecx
  3315 000012FC 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3316 000012FE B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3317                              <1> SD0:
  3318 00001300 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3319 00001301 8025[B5690000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3320                              <1> 	;
  3321                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3322 00001308 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3323                              <1> SD5:
  3324 0000130D E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3325 0000130F A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3326 00001311 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3327                              <1> 	;
  3328 00001313 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3329 00001315 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3330 00001317 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3331                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3332 00001318 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3333                              <1> SD1:
  3334 0000131D F605[B5690000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3335 00001324 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3336 00001326 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3337                              <1> SD2:
  3338 00001328 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3339 0000132A 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3340 0000132C 800D[B5690000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3341 00001333 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3342                              <1> SD3:
  3343 00001335 F605[B5690000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3344 0000133C 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3345                              <1> SD4:	
  3346 0000133E 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3347                              <1> 	;pop	bx
  3348                              <1> 	;pop	ax
  3349                              <1> 	; 05/12/2021
  3350 0000133F 5B                  <1> 	pop	ebx
  3351 00001340 58                  <1> 	pop	eax
  3352 00001341 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3353                              <1> 
  3354                              <1> SND_LED:
  3355                              <1> 	; ---------------------------------------------------------------------------------
  3356                              <1> 	; SND_LED
  3357                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3358                              <1> 	;
  3359                              <1> 	;----------------------------------------------------------------------------------
  3360                              <1> 	;
  3361 00001342 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3362 00001343 F605[B5690000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3363 0000134A 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3364                              <1> 	;
  3365 0000134C 800D[B5690000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3366 00001353 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3367 00001355 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3368 00001357 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3369                              <1> SND_LED1:
  3370 00001359 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3371 0000135A F605[B5690000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3372 00001361 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3373                              <1> 	;
  3374 00001363 800D[B5690000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3375                              <1> SL0:
  3376 0000136A B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3377 0000136C E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3378 00001371 FA                  <1> 	cli
  3379 00001372 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3380 00001377 8025[B5690000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3381 0000137E 0805[B5690000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3382 00001384 F605[B5690000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3383 0000138B 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3384                              <1> 	;
  3385 0000138D E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3386 00001392 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3387 00001393 F605[B5690000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3388 0000139A 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3389                              <1> SL2:
  3390 0000139C B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3391 0000139E E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3392 000013A3 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3393                              <1> SL3:
  3394 000013A4 8025[B5690000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3395                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3396 000013AB FB                  <1> 	sti				; ENABLE INTERRUPTS
  3397 000013AC C3                  <1> 	retn				; RETURN TO CALLER
  3398                              <1> 
  3399                              <1> MAKE_LED:
  3400                              <1> 	;---------------------------------------------------------------------------------
  3401                              <1> 	; MAKE_LED
  3402                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3403                              <1> 	;	THE MODE INDICATORS.
  3404                              <1> 	;---------------------------------------------------------------------------------
  3405                              <1> 	;
  3406                              <1> 	;push 	cx			; SAVE CX
  3407 000013AD A0[B3690000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3408 000013B2 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3409                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3410                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3411 000013B4 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3412 000013B7 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3413                              <1> 	;pop	cx
  3414 000013B9 C3                  <1> 	retn				; RETURN TO CALLER
  3415                              <1> 
  3416                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3417                              <1> 
  3418                              <1> 
  3419                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1850                                  
  1851                                  %include 'video.s' ; 07/03/2015
  1852                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1853                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1854                              <1> ; ****************************************************************************
  1855                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1856                              <1> ; Last Modification: 07/02/2022
  1857                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1858                              <1> ;
  1859                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1860                              <1> 
  1861                              <1> ; 07/02/2022 - Retro UNIX 386 v1.2
  1862                              <1> ; 02/02/2022 - Retro UNIX 386 v1 & v1.1 (simplified scroll up)
  1863                              <1> ; 05/12/2021
  1864                              <1> ; 30/06/2015
  1865                              <1> ; 27/06/2015
  1866                              <1> ; 11/03/2015
  1867                              <1> ; 02/09/2014
  1868                              <1> ; 30/08/2014
  1869                              <1> ; VIDEO FUNCTIONS
  1870                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1871                              <1> 
  1872                              <1> write_tty:
  1873                              <1> 	; 02/02/2022
  1874                              <1> 	; 13/08/2015
  1875                              <1> 	; 02/09/2014
  1876                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1877                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1878                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1879                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1880                              <1> 	;
  1881                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1882                              <1> 	;	   AL = Character to be written
  1883                              <1> 	;	   EBX = Video Page (0 to 7)
  1884                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1885                              <1> 
  1886                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1887                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1888                              <1> 
  1889                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1890                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1891                              <1> ;
  1892                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1893                              <1> ;
  1894                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1895                              <1> ;										:
  1896                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1897                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1898                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1899                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1900                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1901                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1902                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1903                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1904                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1905                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1906                              <1> ;   THE 0 COLOR IS USED.							:
  1907                              <1> ;   ENTRY --									:
  1908                              <1> ;     (AH) = CURRENT CRT MODE							:
  1909                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1910                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1911                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1912                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1913                              <1> ;   EXIT -- 									:
  1914                              <1> ;     ALL REGISTERS SAVED							:
  1915                              <1> ;--------------------------------------------------------------------------------
  1916                              <1> 
  1917 000013BA FA                  <1> 	cli
  1918                              <1> 	;
  1919                              <1> 	; READ CURSOR (04/12/2013)
  1920                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1921 000013BB 08FF                <1> 	or	bh, bh
  1922                              <1> 	;jnz	beeper
  1923                              <1> 	; 02/02/2022
  1924 000013BD 7405                <1> 	jz	short u14
  1925 000013BF E992000000          <1> 	jmp	beeper
  1926                              <1> u14:
  1927                              <1> 	; 02/02/2022
  1928                              <1> 	;; 01/09/2014
  1929                              <1> 	;cmp	byte [CRT_MODE], 3
  1930                              <1> 	;je	short m3
  1931                              <1> 	;;
  1932                              <1> 	;call	set_mode
  1933                              <1> m3:
  1934 000013C4 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1935                              <1> 	;shl	si, 1
  1936                              <1> 	; 02/02/2022
  1937 000013C6 D1E6                <1> 	shl	esi, 1
  1938 000013C8 81C6[A66F0000]      <1> 	add	esi, cursor_posn
  1939 000013CE 668B16              <1> 	mov	dx, [esi]
  1940                              <1> 	;
  1941                              <1> 	; dx now has the current cursor position
  1942                              <1> 	;
  1943 000013D1 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1944 000013D3 7647                <1> 	jbe	short u8
  1945                              <1> 	;
  1946                              <1> 	; write the char to the screen
  1947                              <1> u0:	
  1948                              <1> 	; ah = attribute/color
  1949                              <1> 	; al = character
  1950                              <1> 	; bl = video page number (0 to 7)
  1951                              <1> 	; bh = 0
  1952                              <1> 	;
  1953 000013D5 E8D2010000          <1> 	call	write_c_current
  1954                              <1> 	;
  1955                              <1> 	; position the cursor for next char
  1956 000013DA FEC2                <1> 	inc	dl		; next column
  1957                              <1> 	;cmp	dl, [CRT_COLS]
  1958 000013DC 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1959                              <1>         ;jne	set_cpos
  1960                              <1> 	; 02/02/2022
  1961 000013DF 7405                <1> 	je	short u13
  1962 000013E1 E9DE000000          <1> 	jmp	set_cpos
  1963                              <1> u13:
  1964 000013E6 B200                <1> 	mov	dl, 0		; column = 0
  1965                              <1> u10:				; (line feed found)
  1966 000013E8 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1967 000013EB 7228                <1> 	jb 	short u6
  1968                              <1> 	;
  1969                              <1> 	; scroll required
  1970                              <1> u1:	
  1971                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1972 000013ED E8D2000000          <1> 	call	set_cpos
  1973                              <1> 	;
  1974                              <1> 	; determine value to fill with during scroll
  1975                              <1> u2:
  1976                              <1> 	; READ_AC_CURRENT		:
  1977                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1978                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1979                              <1> 	;
  1980                              <1> 	; INPUT				
  1981                              <1> 	;	(AH) = CURRENT CRT MODE
  1982                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1983                              <1> 	;	(DS) = DATA SEGMENT
  1984                              <1> 	;	(ES) = REGEN SEGMENT
  1985                              <1> 	; OUTPUT			
  1986                              <1> 	;	(AL) = CHARACTER READ
  1987                              <1> 	;	(AH) = ATTRIBUTE READ
  1988                              <1> 	;
  1989                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1990                              <1> 	;
  1991                              <1> 	; bl = video page number
  1992                              <1> 	;
  1993 000013F2 E829010000          <1> 	call	find_position	; get regen location and port address
  1994                              <1> 	; dx = status port
  1995                              <1> 	; esi = cursor location/address
  1996                              <1> p11:
  1997 000013F7 FB                  <1> 	sti			; enable interrupts
  1998 000013F8 90                  <1> 	nop			; allow for small interupts window
  1999 000013F9 FA                  <1> 	cli			; blocks interrupts for single loop
  2000 000013FA EC                  <1> 	in	al, dx		; get status from adapter
  2001 000013FB A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2002 000013FD 75F8                <1> 	jnz	short p11	; wait until it is
  2003                              <1> p12:				; now wait for either retrace high
  2004 000013FF EC                  <1> 	in	al, dx		; get status
  2005 00001400 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2006 00001402 74FB                <1> 	jz	short p12	; wait until either is active	
  2007                              <1> p13:
  2008 00001404 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2009 0000140A 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2010                              <1> 	;
  2011                              <1> 	; al = character, ah = attribute
  2012                              <1> 	;
  2013 0000140D FB                  <1> 	sti
  2014                              <1> 	; bl = video page number 	
  2015                              <1> u3:
  2016                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2017                              <1> 	;;sub	cx, cx		; upper left corner
  2018                              <1> 	;;mov	dh, 25-1 	; lower right row
  2019                              <1> 	;;;mov	dl, [CRT_COLS]
  2020                              <1> 	;mov	dl, 80		; lower right column	
  2021                              <1> 	;;dec	dl
  2022                              <1> 	;;mov	dl, 79
  2023                              <1> 
  2024                              <1> 	;;call	scroll_up	; 04/12/2013
  2025                              <1> 	;;; 11/03/2015
  2026                              <1> 	; 02/09/2014
  2027                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2028                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2029                              <1> 	; 11/03/2015
  2030                              <1> 	;sub	cx, cx
  2031                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2032                              <1> 	;
  2033                              <1> 	; 02/02/2022 (simplied scroll up)
  2034                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2035                              <1> 	;
  2036 0000140E B001                <1> 	mov	al, 1		; scroll 1 line up
  2037                              <1> 		; ah = attribute
  2038 00001410 E935010000          <1> 	jmp	scroll_up
  2039                              <1> ;u4:
  2040                              <1> 	;;int	10h		; video-call return
  2041                              <1> 				; scroll up the screen
  2042                              <1> 				; tty return
  2043                              <1> ;u5:
  2044                              <1> 	;retn			; return to the caller
  2045                              <1> 
  2046                              <1> u6:				; set-cursor-inc
  2047 00001415 FEC6                <1> 	inc	dh		; next row
  2048                              <1> 				; set cursor
  2049                              <1> ;u7:					
  2050                              <1> 	;;mov	ah, 02h
  2051                              <1> 	;;jmp	short u4 	; establish the new cursor
  2052                              <1> 	;call	set_cpos
  2053                              <1> 	;jmp 	short u5
  2054 00001417 E9A8000000          <1> 	jmp     set_cpos
  2055                              <1> 
  2056                              <1> 	; check for control characters
  2057                              <1> u8:
  2058 0000141C 7434                <1> 	je	short u9
  2059 0000141E 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2060 00001420 74C6                <1> 	je	short u10
  2061 00001422 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2062 00001424 7430                <1> 	je	short u11
  2063 00001426 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2064                              <1> 	;jne	short u0
  2065 00001428 7420                <1> 	je	short bs	; 12/12/2013
  2066                              <1> 	; 12/12/2013 (tab stop)
  2067 0000142A 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2068 0000142C 75A7                <1> 	jne	short u0
  2069 0000142E 88D0                <1> 	mov	al, dl
  2070 00001430 6698                <1> 	cbw
  2071 00001432 B108                <1> 	mov	cl, 8
  2072 00001434 F6F1                <1> 	div	cl
  2073 00001436 28E1                <1> 	sub	cl, ah
  2074                              <1> ts:
  2075                              <1> 	; 02/09/2014
  2076                              <1> 	; 01/09/2014
  2077 00001438 B020                <1> 	mov	al, 20h
  2078                              <1> tsloop:
  2079                              <1> 	;push	cx
  2080                              <1> 	;push	ax
  2081                              <1> 	; 02/02/2022
  2082 0000143A 51                  <1> 	push	ecx
  2083 0000143B 50                  <1> 	push	eax
  2084 0000143C 30FF                <1> 	xor 	bh, bh
  2085                              <1> 	;mov	bl, [active_page]
  2086 0000143E E881FFFFFF          <1> 	call	m3
  2087                              <1> 	; 02/02/2022
  2088 00001443 58                  <1> 	pop	eax
  2089 00001444 59                  <1>  	pop	ecx
  2090                              <1> 	;pop	ax  ; ah = attribute/color
  2091                              <1> 	;pop	cx
  2092 00001445 FEC9                <1> 	dec	cl
  2093 00001447 75F1                <1> 	jnz	short tsloop
  2094 00001449 C3                  <1> 	retn
  2095                              <1> bs:	
  2096                              <1> 	; back space found
  2097 0000144A 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2098                              <1> 	;je	short u7 	; set_cursor
  2099 0000144C 7476                <1> 	jz	short set_cpos
  2100                              <1> 	;dec	dx     		; no -- just move it back
  2101                              <1> 	; 02/02/2022
  2102 0000144E FECA                <1> 	dec	dl
  2103                              <1> 	;jmp	short u7
  2104 00001450 EB72                <1> 	jmp	short set_cpos
  2105                              <1> 
  2106                              <1> 	; carriage return found
  2107                              <1> u9:
  2108 00001452 B200                <1> 	mov	dl, 0 		; move to first column
  2109                              <1> 	;jmp	short u7
  2110 00001454 EB6E                <1> 	jmp	short set_cpos
  2111                              <1> 
  2112                              <1> 	; line feed found
  2113                              <1> ;u10:
  2114                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2115                              <1> ;	jne	short u6 	; no, just set the cursor
  2116                              <1> ;       jmp     u1              ; yes, scroll the screen
  2117                              <1> 
  2118                              <1> beeper: 
  2119                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2120                              <1> 	; 18/01/2014
  2121                              <1> 	; 03/12/2013
  2122                              <1> 	; bell found
  2123                              <1> u11:
  2124 00001456 FB                  <1> 	sti
  2125 00001457 3A1D[B66F0000]      <1> 	cmp	bl, [active_page]
  2126 0000145D 7551                <1> 	jne	short u12	; Do not sound the beep 
  2127                              <1> 				; if it is not written on the active page
  2128 0000145F 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2129 00001463 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2130                              <1> 	;call	beep		; sound the pod bell
  2131                              <1> 	;jmp	short u5 	; tty_return
  2132                              <1> 	;retn
  2133                              <1> 	
  2134                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2135                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2136                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2137                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2138                              <1> 
  2139                              <1> beep:
  2140                              <1> 	; 07/02/2015
  2141                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2142                              <1> 	; 18/01/2014
  2143                              <1> 	; 03/12/2013
  2144                              <1> 	;
  2145                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2146                              <1> 	;
  2147                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2148                              <1> 	;
  2149                              <1> 	; ENTRY:
  2150                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2151                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2152                              <1> 	; EXIT:			:
  2153                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2154                              <1> 
  2155 00001465 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2156 00001466 FA                  <1> 	cli			; block interrupts during update
  2157 00001467 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2158 00001469 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2159 0000146B EB00                <1> 	jmp	$+2		; I/O delay
  2160 0000146D 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2161 0000146F E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2162 00001471 EB00                <1> 	jmp	$+2		; I/O delay
  2163 00001473 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2164 00001475 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2165 00001477 E461                <1> 	in	al, PORT_B	; get current setting of port
  2166 00001479 88C4                <1> 	mov	ah, al		; save that setting
  2167 0000147B 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2168 0000147D E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2169                              <1> 	;popf	; 18/01/2014
  2170 0000147F FB                  <1> 	sti
  2171                              <1> g7:				; 1/64 second per count (bl)
  2172 00001480 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2173 00001485 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2174 0000148A FECB                <1> 	dec	bl		; (bl) length count expired?
  2175 0000148C 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2176                              <1> 	;
  2177                              <1> 	;pushf			; save interrupt status
  2178 0000148E FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2179 0000148F E461                <1> 	in	al, PORT_B	; get current port value
  2180                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2181 00001491 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2182 00001493 20C4                <1>         and	ah, al		; someone turned them off during beep
  2183 00001495 88E0                <1> 	mov	al, ah		; recover value of port
  2184                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2185 00001497 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2186 00001499 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2187                              <1> 	;popf			; restore interrupt flag state
  2188 0000149B FB                  <1> 	sti
  2189 0000149C B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2190 000014A1 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2191                              <1> 	;pushf			; save interrupt status
  2192 000014A6 FA                  <1> 	cli			; block interrupts during update
  2193 000014A7 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2194 000014A9 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2195 000014AB 08E0                <1> 	or	al, ah		; recover value of port_b
  2196 000014AD E661                <1> 	out	PORT_B, al	; restore speaker status
  2197 000014AF 9D                  <1> 	popf			; restore interrupt flag state
  2198                              <1> u12:	
  2199 000014B0 C3                  <1> 	retn
  2200                              <1> 
  2201                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2202                              <1> 
  2203                              <1> WAITF:
  2204                              <1> waitf:
  2205                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2206                              <1> 	; 03/12/2013
  2207                              <1> 	;
  2208                              <1> ;	push ax			; save work register (ah)	
  2209                              <1> ;waitf1:
  2210                              <1> 				; use timer 1 output bits
  2211                              <1> ;	in	al, PORT_B	; read current counter output status
  2212                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2213                              <1> ;	cmp	al, ah		; did it just change
  2214                              <1> ;	je	short waitf1	; wait for a change in output line
  2215                              <1> ;	;
  2216                              <1> ;	mov	ah, al		; save new lflag state
  2217                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2218                              <1> ;	;
  2219                              <1> ;	pop	ax		; restore (ah)
  2220                              <1> ;	retn			; return (cx)=0
  2221                              <1> 
  2222                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2223                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2224                              <1> ; 17/12/2014 (dsectrm2.s)
  2225                              <1> ; WAITF
  2226                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2227                              <1> ;
  2228                              <1> ;---WAITF-----------------------------------------------------------------------
  2229                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2230                              <1> ; ENTRY:
  2231                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2232                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2233                              <1> ; EXIT:
  2234                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2235                              <1> ;	(CX) = 0	
  2236                              <1> ;-------------------------------------------------------------------------------
  2237                              <1> 
  2238                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2239                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2240                              <1> 
  2241                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2242                              <1> 	;PUSH	AX			; SAVE WORK REGISTER (AH)
  2243                              <1> 	; 05/12/2021
  2244 000014B1 50                  <1> 	push	eax
  2245                              <1> 	; 16/12/2014
  2246                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2247 000014B2 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2248                              <1> ;17/12/2014	
  2249                              <1> ;WAITF1:
  2250                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2251                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2252                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2253                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2254                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2255                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2256                              <1> 	;
  2257                              <1> 	; 17/12/2014
  2258                              <1> 	;
  2259                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2260                              <1> 	;
  2261                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2262                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2263                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2264                              <1> WR_STATE_0:
  2265 000014B4 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2266 000014B6 A810                <1> 	TEST	AL,010H
  2267 000014B8 74FA                <1> 	JZ	SHORT WR_STATE_0
  2268                              <1> WR_STATE_1:
  2269 000014BA E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2270 000014BC A810                <1> 	TEST	AL,010H
  2271 000014BE 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2272 000014C0 E2F2                <1>         LOOP    WR_STATE_0
  2273                              <1> 	;
  2274                              <1> 	;POP	AX			; RESTORE (AH)
  2275                              <1> 	; 05/12/2021
  2276 000014C2 58                  <1> 	pop	eax
  2277 000014C3 C3                  <1> 	RETn				; (CX) = 0
  2278                              <1> 
  2279                              <1> set_cpos:
  2280                              <1> 	; 02/02/2022
  2281                              <1> 	; 27/06/2015
  2282                              <1> 	; 01/09/2014
  2283                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2284                              <1> 	;
  2285                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2286                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2287                              <1> 	;
  2288                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2289                              <1> 	;
  2290                              <1> 	; SET_CPOS
  2291                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2292                              <1> 	;	NEW X-Y VALUES PASSED
  2293                              <1> 	; INPUT
  2294                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2295                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2296                              <1> 	; OUTPUT
  2297                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2298                              <1> 	;
  2299 000014C4 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2300 000014C7 D0E0                <1>         shl     al, 1   ; word offset
  2301 000014C9 BE[A66F0000]        <1> 	mov	esi, cursor_posn
  2302 000014CE 01C6                <1>         add     esi, eax
  2303 000014D0 668916              <1> 	mov	[esi], dx ; save the pointer
  2304 000014D3 381D[B66F0000]      <1> 	cmp	[active_page], bl
  2305 000014D9 7532                <1> 	jne	short m17
  2306                              <1> 	;call	m18	; CURSOR SET
  2307                              <1> ;m17:			; SET_CPOS_RETURN
  2308                              <1> 	; 01/09/2014
  2309                              <1> ;	retn
  2310                              <1> 		; DX = row/column
  2311                              <1> m18:
  2312 000014DB E832000000          <1> 	call	position ; determine location in regen buffer	
  2313 000014E0 668B0D[A46F0000]    <1> 	mov	cx, [CRT_START]
  2314 000014E7 6601C1              <1> 	add	cx, ax  ; add char position in regen buffer
  2315                              <1> 			; to the start address (offset) for this page
  2316 000014EA 66D1E9              <1> 	shr	cx, 1	; divide by 2 for char only count
  2317 000014ED B40E                <1> 	mov	ah, 14	; register number for cursor
  2318                              <1> 	;call	m16	; output value to the 6845	
  2319                              <1> 	;retn
  2320                              <1> 
  2321                              <1> 	; 02/02/2022
  2322                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2323                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2324                              <1> m16:
  2325 000014EF FA                  <1> 	cli
  2326                              <1> 	;mov	dx, [addr_6845] ; address register
  2327 000014F0 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2328 000014F4 88E0                <1> 	mov	al, ah	; get value
  2329 000014F6 EE                  <1> 	out	dx, al	; register set
  2330                              <1> 	;inc	dx	; data register
  2331                              <1> 	; 02/02/2022
  2332 000014F7 FEC2                <1> 	inc	dl
  2333 000014F9 EB00                <1> 	jmp	$+2	; i/o delay
  2334 000014FB 88E8                <1> 	mov	al, ch	; data
  2335 000014FD EE                  <1> 	out	dx, al	
  2336                              <1> 	;dec	dx
  2337                              <1> 	; 02/02/2022	
  2338 000014FE FECA                <1> 	dec	dl
  2339 00001500 88E0                <1> 	mov	al, ah
  2340 00001502 FEC0                <1> 	inc	al	; point to other data register
  2341 00001504 EE                  <1> 	out	dx, al	; set for second register
  2342                              <1> 	;inc	dx
  2343                              <1> 	; 02/02/2022
  2344 00001505 FEC2                <1> 	inc	dl
  2345 00001507 EB00                <1> 	jmp	$+2	; i/o delay
  2346 00001509 88C8                <1> 	mov	al, cl	; second data value
  2347 0000150B EE                  <1> 	out	dx, al
  2348 0000150C FB                  <1> 	sti
  2349                              <1> m17:
  2350 0000150D C3                  <1> 	retn
  2351                              <1> 
  2352                              <1> set_ctype:
  2353                              <1> 	; 07/02/2022
  2354                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2355                              <1> 	;
  2356                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2357                              <1> 
  2358                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2359                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2360                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2361                              <1> ;          OR NO CURSOR AT ALL
  2362                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2363                              <1> 
  2364                              <1> ;------------------------------------------------
  2365                              <1> ; SET_CTYPE
  2366                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2367                              <1> ; INPUT
  2368                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2369                              <1> ; OUTPUT	
  2370                              <1> ;	NONE
  2371                              <1> ;------------------------------------------------
  2372                              <1> 
  2373 0000150E B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2374                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2375                              <1> 	;call	m16	; output cx register
  2376                              <1> 	;retn
  2377                              <1> 	; 07/02/2022
  2378 00001510 EBDD                <1> 	jmp	short m16
  2379                              <1> 
  2380                              <1> position:
  2381                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2382                              <1> 	; 27/06/2015
  2383                              <1> 	; 02/09/2014
  2384                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2385                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2386                              <1> 	;
  2387                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2388                              <1> 	;
  2389                              <1> 	; POSITION
  2390                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2391                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2392                              <1> 	; INPUT
  2393                              <1> 	;	AX = ROW, COLUMN POSITION
  2394                              <1> 	; OUTPUT
  2395                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2396                              <1> 
  2397                              <1> 		; DX = ROW, COLUMN POSITION
  2398                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2399 00001512 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2400 00001514 B050                <1> 	mov	al, 80   ; determine bytes to row	
  2401 00001516 F6E6                <1> 	mul	dh 	 ; row value
  2402 00001518 30F6                <1> 	xor	dh, dh   ; 0	
  2403 0000151A 6601D0              <1> 	add	ax, dx	 ; add column value to the result
  2404                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2405                              <1> 	; 05/12/2021
  2406 0000151D D1E0                <1> 	shl	eax, 1
  2407                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2408 0000151F C3                  <1> 	retn
  2409                              <1> 
  2410                              <1> find_position:
  2411                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2412                              <1> 	; 27/06/2015
  2413                              <1> 	; 07/09/2014
  2414                              <1> 	; 02/09/2014
  2415                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2416                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2417 00001520 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2418 00001523 89CE                <1> 	mov	esi, ecx
  2419                              <1> 	;shl	si, 1
  2420 00001525 D1E6                <1> 	shl	esi, 1 ; 05/12/2021
  2421 00001527 668B96[A66F0000]    <1> 	mov	dx, [esi+cursor_posn]
  2422 0000152E 7409                <1> 	jz	short p21
  2423                              <1> 	;xor	si, si
  2424 00001530 31F6                <1> 	xor	esi, esi ; 05/12/2021
  2425                              <1> p20:
  2426                              <1> 	;add	si, [CRT_LEN]
  2427 00001532 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2428 00001537 E2F9                <1> 	loop	p20
  2429                              <1> p21:
  2430 00001539 6621D2              <1> 	and	dx, dx
  2431 0000153C 7407                <1> 	jz	short p22
  2432 0000153E E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2433 00001543 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2434                              <1> p22:	
  2435                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2436                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2437                              <1> 	;add	dx, 6	; point at status port
  2438 00001545 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2439                              <1> 	; cx = 0
  2440 00001549 C3                  <1> 	retn
  2441                              <1> 
  2442                              <1> scroll_up:
  2443                              <1> 	; 07/02/2022 - Retro UNIX 386 v1.2
  2444                              <1> 	; 02/02/2022  (simplified scroll up)
  2445                              <1> 	;	     - Retro UNIX 386 v1.1 
  2446                              <1> 	;	     - Retro UNIX 386 v1.0)
  2447                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2448                              <1> 	; 16/01/2016
  2449                              <1> 	; 07/09/2014
  2450                              <1> 	; 02/09/2014
  2451                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2452                              <1> 	; 04/04/2014
  2453                              <1> 	; 04/12/2013
  2454                              <1> 	;
  2455                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2456                              <1> 	;
  2457                              <1> 	; SCROLL UP
  2458                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2459                              <1> 	;	ON THE SCREEN
  2460                              <1> 	; INPUT
  2461                              <1> 	;	(AH) = CURRENT CRT MODE
  2462                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2463                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2464                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2465                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2466                              <1> 	;	(DS) = DATA SEGMENT
  2467                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2468                              <1> 	; OUTPUT
  2469                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2470                              <1> 	;
  2471                              <1> 	;	bh = 0  (02/09/2014)
  2472                              <1> 	;
  2473                              <1> 	; ((ah = 3))
  2474                              <1> 	; cl = left upper column
  2475                              <1> 	; ch = left upper row
  2476                              <1> 	; dl = right lower column
  2477                              <1> 	; dh = right lower row
  2478                              <1> 	;
  2479                              <1> 	; al = line count 
  2480                              <1> 	; ah = attribute to be used on blanked line
  2481                              <1> 	; bl = video page number (0 to 7)
  2482                              <1> 	; 
  2483                              <1> 
  2484                              <1> 	; 02/02/2022 'scroll_up' code
  2485                              <1> 	; ------------------------------------------------------
  2486                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2487                              <1> 
  2488                              <1> 	; INPUT:
  2489                              <1> 	;		
  2490                              <1> 	; al = line count 
  2491                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2492                              <1> 	; ah = attribute to be used on blanked line
  2493                              <1> 	; bl = video page number (0 to 7)
  2494                              <1> 
  2495                              <1> 	;cli
  2496 0000154A 31C9                <1> 	xor	ecx, ecx
  2497 0000154C 88C1                <1> 	mov	cl, al ; line count (cl)
  2498 0000154E BE00800B00          <1> 	mov	esi, 0B8000h
  2499 00001553 3A1D[B66F0000]      <1> 	cmp	bl, [active_page]
  2500 00001559 7411                <1> 	je	short n1
  2501 0000155B 20DB                <1> 	and	bl, bl
  2502 0000155D 7422                <1> 	jz	short n3
  2503 0000155F 88DD                <1> 	mov	ch, bl ; video page number
  2504                              <1> n0:
  2505 00001561 6681C6A00F          <1> 	add	si, 25*80*2
  2506 00001566 FECD                <1> 	dec	ch
  2507 00001568 75F7                <1> 	jnz	short n0
  2508 0000156A EB15                <1> 	jmp	short n3
  2509                              <1> n1:
  2510 0000156C 660335[A46F0000]    <1> 	add	si, [CRT_START]
  2511                              <1> 	;
  2512 00001573 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2513                              <1> n2:			 ; wait_display_enable
  2514 00001577 EC                  <1> 	in	al, dx	 ; get port
  2515 00001578 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2516 0000157A 74FB                <1> 	jz	short n2 ; wait_display_enable
  2517 0000157C B025                <1> 	mov	al, 25h
  2518 0000157E B2D8                <1> 	mov	dl, 0D8h ; address control port
  2519 00001580 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2520                              <1> n3:
  2521                              <1> 	; cl = line count
  2522                              <1> 	; ah = attribute/color
  2523 00001581 89F7                <1> 	mov	edi, esi
  2524 00001583 20C9                <1> 	and	cl, cl
  2525 00001585 741F                <1> 	jz	short n6
  2526 00001587 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2527 0000158C 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2528 00001590 F366A5              <1> 	rep	movsw
  2529 00001593 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2530                              <1> n4:
  2531                              <1> 	; ah = character attribute/cocor
  2532 00001595 B020                <1> 	mov	al, 20h ; fill with blanks
  2533 00001597 F366AB              <1> 	rep	stosw
  2534                              <1> 
  2535 0000159A 3A1D[B66F0000]      <1> 	cmp	bl, [active_page]
  2536 000015A0 7503                <1> 	jne	short n5
  2537                              <1> 
  2538                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2539 000015A2 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2540                              <1> 	;mov	dx, 03D8h ; always set color card port
  2541 000015A4 EE                  <1> 	out	dx, al
  2542                              <1> n5:
  2543 000015A5 C3                  <1> 	retn
  2544                              <1> n6:
  2545                              <1> 	; clear video page
  2546 000015A6 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2547 000015AA EBE9                <1> 	jmp	short n4
  2548                              <1> 
  2549                              <1> %if 0
  2550                              <1> 
  2551                              <1> scroll_up:
  2552                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2553                              <1> 	; 16/01/2016
  2554                              <1> 	; 07/09/2014
  2555                              <1> 	; 02/09/2014
  2556                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2557                              <1> 	; 04/04/2014
  2558                              <1> 	; 04/12/2013
  2559                              <1> 	;
  2560                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2561                              <1> 	;
  2562                              <1> 	; SCROLL UP
  2563                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2564                              <1> 	;	ON THE SCREEN
  2565                              <1> 	; INPUT
  2566                              <1> 	;	(AH) = CURRENT CRT MODE
  2567                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2568                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2569                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2570                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2571                              <1> 	;	(DS) = DATA SEGMENT
  2572                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2573                              <1> 	; OUTPUT
  2574                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2575                              <1> 	;
  2576                              <1> 	;	bh = 0  (02/09/2014)
  2577                              <1> 	;
  2578                              <1> 	; ((ah = 3))
  2579                              <1> 	; cl = left upper column
  2580                              <1> 	; ch = left upper row
  2581                              <1> 	; dl = right lower column
  2582                              <1> 	; dh = right lower row
  2583                              <1> 	;
  2584                              <1> 	; al = line count 
  2585                              <1> 	; ah = attribute to be used on blanked line	
  2586                              <1> 	; bl = video page number (0 to 7)
  2587                              <1> 	; 
  2588                              <1> 
  2589                              <1> 	; Test	Line Count
  2590                              <1> 	or	al, al
  2591                              <1> 	jz	short al_set
  2592                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2593                              <1> 	sub	bh, ch
  2594                              <1> 	inc	bh	; adjust difference by 1
  2595                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2596                              <1> 	jne	short al_set ; if not the we're all set
  2597                              <1> 	xor	al, al	; otherwise set al to zero
  2598                              <1> al_set:
  2599                              <1> 	xor	bh, bh	; 0
  2600                              <1> 	;push	ax
  2601                              <1> 	push	eax ; 05/12/2021
  2602                              <1> 	;mov 	esi, [crt_base]
  2603                              <1>         mov     esi, 0B8000h  
  2604                              <1>         cmp     bl, [active_page]
  2605                              <1> 	jne	short n0
  2606                              <1> 	;
  2607                              <1>         mov     ax, [CRT_START]
  2608                              <1>         add     si, ax
  2609                              <1>         jmp     short n1
  2610                              <1> n0:
  2611                              <1>         and     bl, bl
  2612                              <1> 	jz	short n1
  2613                              <1> 	mov	al, bl
  2614                              <1> n0x:
  2615                              <1>         ;add    si, [CRT_LEN]
  2616                              <1>         ;add    esi, 80*25*2 
  2617                              <1>         add     si, 80*25*2
  2618                              <1>         dec	al
  2619                              <1> 	jnz	short n0x
  2620                              <1> n1:	
  2621                              <1>         ;Scroll position
  2622                              <1> 	;push	dx
  2623                              <1> 	; 05/12/2021
  2624                              <1> 	push	edx
  2625                              <1> 	mov	dx, cx	; now, upper left position in DX
  2626                              <1> 	call	position
  2627                              <1> 	add	esi, eax
  2628                              <1> 	mov	edi, esi
  2629                              <1> 	;pop	dx	; lower right position in DX
  2630                              <1> 	pop	edx ; 05/12/2021
  2631                              <1> 	sub	dx, cx
  2632                              <1> 	inc	dh	; dh = #rows 
  2633                              <1> 	inc	dl	; dl = #cols in block
  2634                              <1> 	;pop	ax	; al = line count, ah = attribute
  2635                              <1> 	; 05/12/2021
  2636                              <1> 	pop	eax	; al = line count, ah = attribute
  2637                              <1> 	xor	ecx, ecx
  2638                              <1> 	mov	cx, ax
  2639                              <1> 	;mov	ah, [CRT_COLS]
  2640                              <1> 	mov	ah, 80
  2641                              <1> 	mul	ah	; determine offset to from address
  2642                              <1> 	add	ax, ax  ; *2 for attribute byte
  2643                              <1> 	;
  2644                              <1> 	;push	ax	; offset 
  2645                              <1> 	;push	dx
  2646                              <1> 	; 05/12/2021
  2647                              <1> 	push	eax
  2648                              <1> 	push	edx
  2649                              <1> 	;
  2650                              <1> 	; 04/04/2014
  2651                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2652                              <1> n8:                      ; wait_display_enable
  2653                              <1>         in      al, dx   ; get port
  2654                              <1> 	test	al, RVRT ; wait for vertical retrace	
  2655                              <1> 	jz	short n8 ; wait_display_enable
  2656                              <1> 	mov	al, 25h
  2657                              <1> 	mov	dl, 0D8h ; address control port
  2658                              <1> 	out	dx, al	; turn off video during vertical retrace
  2659                              <1> 	;pop	dx	; #rows, #cols
  2660                              <1>        	;pop	ax	; offset
  2661                              <1> 	; 05/12/2021
  2662                              <1> 	pop	edx
  2663                              <1> 	pop	eax
  2664                              <1> 	xchg	ax, cx	; 
  2665                              <1> 	; ecx = offset, al = line count, ah = attribute
  2666                              <1> ;n9:
  2667                              <1> 	or	al, al
  2668                              <1>         jz      short n3 
  2669                              <1>         add     esi, ecx ; from address for scroll
  2670                              <1> 	mov	bh, dh  ; #rows in block
  2671                              <1> 	sub	bh, al	; #rows to be moved
  2672                              <1> n2:
  2673                              <1> 	; Move rows
  2674                              <1> 	mov	cl, dl	; get # of cols to move
  2675                              <1> 	push	esi
  2676                              <1> 	push	edi	; save start address
  2677                              <1> n10:
  2678                              <1> 	movsw		; move that line on screen
  2679                              <1> 	dec	cl
  2680                              <1>         jnz     short n10
  2681                              <1> 	pop	edi
  2682                              <1> 	pop	esi	; recover addresses
  2683                              <1>         ;mov    cl, [CRT_COLS] 
  2684                              <1> 	;add	cl, cl
  2685                              <1>         ;mov    ecx, 80*2
  2686                              <1>         mov     cx, 80*2
  2687                              <1>         add     esi, ecx  ; next line
  2688                              <1>         add     edi, ecx
  2689                              <1> 	dec	bh	 ; count of lines to move
  2690                              <1> 	jnz	short n2 ; row loop
  2691                              <1> 	; bh = 0
  2692                              <1> 	mov	dh, al	 ; #rows	
  2693                              <1> n3:
  2694                              <1> 	; attribute in ah
  2695                              <1> 	mov	al, ' '	 ; fill with blanks
  2696                              <1> n3x:
  2697                              <1> 	; Clear rows
  2698                              <1>                 ; dh =  #rows
  2699                              <1>         mov	cl, dl	; get # of cols to clear
  2700                              <1>         push    edi     ; save address
  2701                              <1> n11:
  2702                              <1>         stosw           ; store fill character
  2703                              <1> 	dec	cl
  2704                              <1>         jnz     short n11
  2705                              <1>         pop     edi     ; recover address
  2706                              <1> 	;mov	cl, [CRT_COLS]
  2707                              <1> 	;add	cl, cl
  2708                              <1>         ;mov    ecx, 80*2
  2709                              <1>         mov	cl, 80*2
  2710                              <1>         add     edi, ecx
  2711                              <1> 	dec	dh
  2712                              <1> 	jnz	short n3x ; 16/01/2016
  2713                              <1> 	;
  2714                              <1> 	cmp	bl, [active_page]
  2715                              <1> 	jne	short n6
  2716                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2717                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2718                              <1> 	mov	dx, 03D8h ; always set color card port
  2719                              <1> 	out	dx, al
  2720                              <1> n6:
  2721                              <1> 	retn
  2722                              <1> 
  2723                              <1> %endif
  2724                              <1> 
  2725                              <1> write_c_current:
  2726                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2727                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2728                              <1> 	; 18/01/2014
  2729                              <1> 	; 04/12/2013
  2730                              <1> 	;
  2731                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2732                              <1> 	;
  2733                              <1> 	; WRITE_C_CURRENT
  2734                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2735                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2736                              <1> 	; INPUT	
  2737                              <1> 	;	(AH) = CURRENT CRT MODE
  2738                              <1> 	;	(BH) = DISPLAY PAGE
  2739                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2740                              <1> 	;	(AL) = CHAR TO WRITE
  2741                              <1> 	;	(DS) = DATA SEGMENT
  2742                              <1> 	;	(ES) = REGEN SEGMENT
  2743                              <1> 	; OUTPUT
  2744                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2745                              <1> 
  2746 000015AC FA                  <1> 	cli		
  2747                              <1> 	; bl = video page
  2748                              <1> 	; al = character
  2749                              <1> 	; ah = color/attribute
  2750                              <1> 	;push	dx
  2751                              <1> 	;push	ax	; save character & attribute/color
  2752                              <1> 	; 05/12/2021
  2753 000015AD 52                  <1> 	push	edx
  2754 000015AE 50                  <1> 	push	eax
  2755 000015AF E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2756                              <1> 	; esi = regen location
  2757                              <1> 	; dx = status port
  2758                              <1> 	;
  2759                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2760                              <1> 	;
  2761                              <1> p41:			; wait for horizontal retrace is low or vertical
  2762 000015B4 FB                  <1> 	sti		; enable interrupts first
  2763 000015B5 3A1D[B66F0000]      <1>         cmp     bl, [active_page]
  2764 000015BB 7510                <1> 	jne	short p44 
  2765 000015BD FA                  <1> 	cli 		; block interrupts for single loop
  2766 000015BE EC                  <1> 	in	al, dx	; get status from the adapter
  2767 000015BF A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2768 000015C1 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2769 000015C3 A801                <1> 	test	al, RHRZ ; is horizontal retrace low
  2770 000015C5 75ED                <1> 	jnz	short p41 ; wait until it is
  2771                              <1> p42:			;  wait for either retrace high
  2772 000015C7 EC                  <1> 	in	al, dx ; get status again
  2773 000015C8 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2774 000015CA 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2775                              <1> p43:	
  2776 000015CC FB                  <1> 	sti
  2777                              <1> p44:
  2778                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2779                              <1> 	; 05/12/2021
  2780 000015CD 58                  <1> 	pop	eax
  2781 000015CE 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2782                              <1> 				; Retro UNIX 386 v1 feature only!
  2783 000015D4 668906              <1> 	mov	[esi], ax
  2784                              <1> 	;pop	dx
  2785                              <1> 	; 05/12/2021
  2786 000015D7 5A                  <1> 	pop	edx
  2787 000015D8 C3                  <1> 	retn
  2788                              <1> 
  2789                              <1> %if 0	; 02/02/2022
  2790                              <1> 
  2791                              <1> set_mode:
  2792                              <1> 	; 02/02/2022
  2793                              <1> 	; 16/01/2016
  2794                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2795                              <1> 	;
  2796                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2797                              <1> 
  2798                              <1> ;------------------------------------------------------
  2799                              <1> ; SET MODE					      :
  2800                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2801                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2802                              <1> ; INPUT						      :
  2803                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2804                              <1> ; OUTPUT					      :
  2805                              <1> ;	NONE					      :
  2806                              <1> ;------------------------------------------------------
  2807                              <1> 
  2808                              <1> 	push	edi ; 16/01/2016
  2809                              <1> 	push	ebx
  2810                              <1> 	push	edx
  2811                              <1> 	push	ecx ; 16/01/2016
  2812                              <1>         push    eax
  2813                              <1> 
  2814                              <1> 	;mov	dx, 03D4h 	; address or color card
  2815                              <1> 	mov	al, 3
  2816                              <1> ;M8:
  2817                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2818                              <1> 	mov	al, 29h
  2819                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2820                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2821                              <1> 	;push	dx  		; save port value
  2822                              <1> 	;add	dx, 4		; point to control register
  2823                              <1> 	mov	dx, 3D8h
  2824                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2825                              <1> 	;pop	dx
  2826                              <1> ;M9:
  2827                              <1> 	mov	ebx, video_params ; initialization table
  2828                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2829                              <1> 	;xchg 	ah, al
  2830                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2831                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2832                              <1> 	
  2833                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2834                              <1> 	; 02/02/2022
  2835                              <1> 	; dx = 3D8h
  2836                              <1> 	xor	ecx, ecx
  2837                              <1> 	mov	cl, 16
  2838                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2839                              <1> M10:			;  initialization loop
  2840                              <1> 	mov	al, ah 	; get 6845 register number
  2841                              <1> 	out	dx, al
  2842                              <1> 	;inc	dx      ; point to data port
  2843                              <1> 	; 02/02/2022
  2844                              <1> 	inc	dl ; 3D9h
  2845                              <1> 	inc	ah	; next register value
  2846                              <1> 	mov	al, [ebx] ; get table value
  2847                              <1> 	out	dx, al	; out to chip
  2848                              <1> 	inc	ebx	; next in table
  2849                              <1> 	;dec	dx	; back to pointer register
  2850                              <1> 	; 02/02/2022
  2851                              <1> 	dec	dl ; 3D8h
  2852                              <1> 	loop	M10	; do the whole table
  2853                              <1> 	
  2854                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2855                              <1> 	;xor	ax, ax  
  2856                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2857                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2858                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2859                              <1> 	; black background, light gray characeter color, space character
  2860                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2861                              <1> ;M13:			  ; clear buffer
  2862                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2863                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2864                              <1> 
  2865                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2866                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2867                              <1> 			 ; prepare to output to video enable port
  2868                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2869                              <1> 	; 02/02/2022
  2870                              <1> 	;mov	dx, 3D8h
  2871                              <1> 	; 
  2872                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2873                              <1> 	mov	al, 29h
  2874                              <1> 	out	dx, al	 ; set video enable port
  2875                              <1> 
  2876                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2877                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2878                              <1> 	;
  2879                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2880                              <1> 	;
  2881                              <1> ;-----	SET CURSOR POSITIONS
  2882                              <1> 	;push	edi
  2883                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2884                              <1> 	mov	edi, cursor_posn
  2885                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2886                              <1> 	xor	eax, eax
  2887                              <1> 	rep 	stosd	; fill with zeroes
  2888                              <1> 	;pop	edi
  2889                              <1> 
  2890                              <1> ;-----	SET UP OVERSCAN REGISTER
  2891                              <1> 	inc	dx	; set overscan port to a default
  2892                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2893                              <1> ;M14:
  2894                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2895                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2896                              <1> 
  2897                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2898                              <1> 	;
  2899                              <1> 	pop	eax
  2900                              <1> 	pop	ecx ; 16/01/2016
  2901                              <1> 	pop	edx
  2902                              <1> 	pop	ebx
  2903                              <1> 	pop	edi ; 16/01/2016
  2904                              <1> 	retn
  2905                              <1> 
  2906                              <1> %endif
  2907                              <1> 	
  2908                              <1> tty_sw:
  2909                              <1> 	; 07/02/2022
  2910                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2911                              <1> 	; 30/06/2015
  2912                              <1> 	; 27/06/2015 
  2913                              <1> 	; 07/09/2014
  2914                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2915                              <1> 	;
  2916                              <1> 	; (Modified registers : EAX)
  2917                              <1> 	;
  2918                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2919                              <1> 	;
  2920                              <1> ;act_disp_page:
  2921                              <1> 	; 30/06/2015
  2922                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2923                              <1> 	; 10/12/2013
  2924                              <1> 	; 04/12/2013
  2925                              <1> 	;
  2926                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2927                              <1> 	;
  2928                              <1> 	; ACT_DISP_PAGE
  2929                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2930                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2931                              <1> 	; INPUT
  2932                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2933                              <1> 	; OUTPUT
  2934                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2935                              <1> 
  2936                              <1> 	;cli
  2937                              <1> 
  2938 000015D9 53                  <1> 	push	ebx
  2939                              <1> 	;push	cx
  2940                              <1> 	;push	dx
  2941                              <1> 	; 05/12/2021
  2942 000015DA 51                  <1> 	push	ecx
  2943 000015DB 52                  <1> 	push	edx
  2944                              <1> 	;
  2945 000015DC A2[B66F0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2946                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2947                              <1> 	;mov	cx, 25*80*2
  2948                              <1> 	; 07/02/2022
  2949 000015E1 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2950                              <1> 	; 27/06/2015
  2951 000015E6 0FB6D8              <1> 	movzx	ebx, al
  2952                              <1> 	; 07/02/2022
  2953 000015E9 89D8                <1> 	mov	eax, ebx
  2954                              <1> 	;
  2955                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2956                              <1> 	;mul 	cx	; display page times regen length
  2957                              <1> 	; 07/02/2022
  2958 000015EB F7E1                <1> 	mul	ecx	
  2959                              <1> 	; 10/12/2013
  2960 000015ED 66A3[A46F0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2961                              <1> 	;mov	cx, ax	; start address to cx
  2962                              <1> 	; 07/02/2022
  2963 000015F3 89C1                <1> 	mov	ecx, eax
  2964                              <1> 	;sar	cx, 1
  2965                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2966                              <1> 	; 07/02/2022
  2967 000015F5 D1E9                <1> 	shr	ecx, 1
  2968 000015F7 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2969 000015F9 E8F1FEFFFF          <1> 	call	m16
  2970                              <1> 	;sal	bx, 1
  2971                              <1> 	; 01/09/2014
  2972 000015FE D0E3                <1> 	shl	bl, 1	; *2 for word offset
  2973 00001600 81C3[A66F0000]      <1> 	add	ebx, cursor_posn
  2974 00001606 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2975 00001609 E8CDFEFFFF          <1> 	call	m18
  2976                              <1> 	;
  2977                              <1> 	;pop	dx
  2978                              <1> 	;pop	cx
  2979                              <1> 	; 05/12/2021
  2980 0000160E 5A                  <1> 	pop	edx
  2981 0000160F 59                  <1> 	pop	ecx
  2982 00001610 5B                  <1> 	pop	ebx
  2983                              <1> 	;
  2984                              <1> 	;sti
  2985                              <1> 	;
  2986 00001611 C3                  <1> 	retn
  2987                              <1> 
  2988                              <1> ; % include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2989                              <1> 
  2990                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1852                                  
  1853                                  setup_rtc_int:
  1854                                  ; source: http://wiki.osdev.org/RTC
  1855 00001612 FA                      	cli		; disable interrupts
  1856                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1857                                  	; in order to change this ...
  1858                                  	; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1859                                  	; (rate must be above 2 and not over 15)
  1860                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1861 00001613 B08A                    	mov	al, 8Ah 
  1862 00001615 E670                    	out	70h, al ; set index to register A, disable NMI
  1863 00001617 90                      	nop
  1864 00001618 E471                    	in	al, 71h ; get initial value of register A
  1865 0000161A 88C4                    	mov 	ah, al
  1866 0000161C 80E4F0                  	and	ah, 0F0h
  1867 0000161F B08A                    	mov	al, 8Ah 
  1868 00001621 E670                    	out	70h, al ; reset index to register A
  1869 00001623 88E0                    	mov	al, ah
  1870 00001625 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1871 00001627 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1872                                  	; enable RTC interrupt
  1873 00001629 B08B                    	mov	al, 8Bh ;
  1874 0000162B E670                    	out	70h, al ; select register B and disable NMI
  1875 0000162D 90                      	nop
  1876 0000162E E471                    	in	al, 71h ; read the current value of register B
  1877 00001630 88C4                    	mov	ah, al  ;
  1878 00001632 B08B                    	mov 	al, 8Bh ;
  1879 00001634 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1880 00001636 88E0                    	mov	al, ah  ;
  1881 00001638 0C40                    	or	al, 40h ;
  1882 0000163A E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1883 0000163C FB                      	sti
  1884 0000163D C3                      	retn
  1885                                  
  1886                                  ; Write memory information
  1887                                  ; Temporary Code
  1888                                  ; 06/11/2014
  1889                                  ; 14/08/2015 
  1890                                  memory_info:	
  1891 0000163E A1[8C6F0000]            	mov	eax, [memory_size] ; in pages
  1892 00001643 50                      	push	eax
  1893 00001644 C1E00C                  	shl	eax, 12		   ; in bytes
  1894 00001647 BB0A000000              	mov	ebx, 10
  1895 0000164C 89D9                    	mov	ecx, ebx	   ; 10
  1896 0000164E BE[F16B0000]            	mov	esi, mem_total_b_str	
  1897 00001653 E8AE000000              	call	bintdstr
  1898 00001658 58                      	pop	eax
  1899 00001659 B107                    	mov	cl, 7
  1900 0000165B BE[156C0000]            	mov	esi, mem_total_p_str
  1901 00001660 E8A1000000              	call	bintdstr	
  1902                                  	; 14/08/2015
  1903 00001665 E8B9000000              	call	calc_free_mem
  1904                                  	; edx = calculated free pages
  1905                                  	; ecx = 0
  1906 0000166A A1[906F0000]            	mov 	eax, [free_pages]
  1907 0000166F 39D0                    	cmp	eax, edx ; calculated free mem value 
  1908                                  		; and initial free mem value are same or not?
  1909 00001671 751D                    	jne 	short pmim ; print mem info with '?' if not
  1910 00001673 52                      	push 	edx ; free memory in pages	
  1911                                  	;mov 	eax, edx
  1912 00001674 C1E00C                  	shl	eax, 12 ; convert page count
  1913                                  			; to byte count
  1914 00001677 B10A                    	mov	cl, 10
  1915 00001679 BE[356C0000]            	mov	esi, free_mem_b_str
  1916 0000167E E883000000              	call	bintdstr
  1917 00001683 58                      	pop	eax
  1918 00001684 B107                    	mov	cl, 7
  1919 00001686 BE[596C0000]            	mov	esi, free_mem_p_str
  1920 0000168B E876000000              	call	bintdstr
  1921                                  pmim:
  1922 00001690 BE[DF6B0000]            	mov	esi, msg_memory_info
  1923                                  pmim_nb:	
  1924 00001695 AC                      	lodsb
  1925 00001696 08C0                    	or	al, al
  1926 00001698 740D                    	jz	short pmim_ok
  1927 0000169A 56                      	push	esi
  1928 0000169B 31DB                    	xor	ebx, ebx ; 0
  1929                                  			; Video page 0 (bl=0)
  1930 0000169D B407                    	mov	ah, 07h ; Black background, 
  1931                                  			; light gray forecolor
  1932 0000169F E816FDFFFF              	call	write_tty
  1933 000016A4 5E                      	pop	esi
  1934 000016A5 EBEE                    	jmp	short pmim_nb
  1935                                  pmim_ok:
  1936 000016A7 C3                      	retn
  1937                                  
  1938                                  ; Convert binary number to hexadecimal string
  1939                                  ; 10/05/2015  
  1940                                  ; dsectpm.s (28/02/2015)
  1941                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1942                                  ; 01/12/2014
  1943                                  ; 25/11/2014
  1944                                  ;
  1945                                  bytetohex:
  1946                                  	; INPUT ->
  1947                                  	; 	AL = byte (binary number)
  1948                                  	; OUTPUT ->
  1949                                  	;	AX = hexadecimal string
  1950                                  	;
  1951 000016A8 53                      	push	ebx
  1952 000016A9 31DB                    	xor	ebx, ebx
  1953 000016AB 88C3                    	mov	bl, al
  1954 000016AD C0EB04                  	shr	bl, 4
  1955 000016B0 8A9B[F6160000]          	mov	bl, [ebx+hexchrs]
  1956 000016B6 86D8                    	xchg	bl, al
  1957 000016B8 80E30F                  	and	bl, 0Fh
  1958 000016BB 8AA3[F6160000]          	mov	ah, [ebx+hexchrs]
  1959 000016C1 5B                      	pop	ebx	
  1960 000016C2 C3                      	retn
  1961                                  
  1962                                  wordtohex:
  1963                                  	; INPUT ->
  1964                                  	; 	AX = word (binary number)
  1965                                  	; OUTPUT ->
  1966                                  	;	EAX = hexadecimal string
  1967                                  	;
  1968 000016C3 53                      	push	ebx
  1969 000016C4 31DB                    	xor	ebx, ebx
  1970 000016C6 86E0                    	xchg	ah, al
  1971 000016C8 6650                    	push	ax
  1972 000016CA 88E3                    	mov	bl, ah
  1973 000016CC C0EB04                  	shr	bl, 4
  1974 000016CF 8A83[F6160000]          	mov	al, [ebx+hexchrs]
  1975 000016D5 88E3                    	mov	bl, ah
  1976 000016D7 80E30F                  	and	bl, 0Fh
  1977 000016DA 8AA3[F6160000]          	mov	ah, [ebx+hexchrs]
  1978 000016E0 C1E010                  	shl	eax, 16
  1979 000016E3 6658                    	pop	ax
  1980 000016E5 5B                      	pop	ebx
  1981 000016E6 EBC0                    	jmp	short bytetohex
  1982                                  	;mov	bl, al
  1983                                  	;shr	bl, 4
  1984                                  	;mov	bl, [ebx+hexchrs]
  1985                                  	;xchg	bl, al	 	
  1986                                  	;and	bl, 0Fh
  1987                                  	;mov	ah, [ebx+hexchrs]
  1988                                  	;pop	ebx	
  1989                                  	;retn
  1990                                  
  1991                                  dwordtohex:
  1992                                  	; INPUT ->
  1993                                  	; 	EAX = dword (binary number)
  1994                                  	; OUTPUT ->
  1995                                  	;	EDX:EAX = hexadecimal string
  1996                                  	;
  1997 000016E8 50                      	push	eax
  1998 000016E9 C1E810                  	shr	eax, 16
  1999 000016EC E8D2FFFFFF              	call	wordtohex
  2000 000016F1 89C2                    	mov	edx, eax
  2001 000016F3 58                      	pop	eax
  2002                                  	;call	wordtohex
  2003                                  	;retn
  2004                                  	; 02/01/2022
  2005 000016F4 EBCD                    	jmp	short wordtohex
  2006                                  
  2007                                  ; 10/05/2015
  2008                                  hex_digits:
  2009                                  hexchrs:
  2010 000016F6 303132333435363738-     	db '0123456789ABCDEF'
  2010 000016FF 39414243444546     
  2011                                  
  2012                                  ; Convert binary number to decimal/numeric string
  2013                                  ; 06/11/2014
  2014                                  ; Temporary Code
  2015                                  ;
  2016                                  
  2017                                  bintdstr:
  2018                                  	; EAX = binary number
  2019                                  	; ESI = decimal/numeric string address
  2020                                  	; EBX = divisor (10)
  2021                                  	; ECX = string length (<=10)
  2022 00001706 01CE                    	add	esi, ecx
  2023                                  btdstr0:
  2024 00001708 4E                      	dec	esi
  2025 00001709 31D2                    	xor	edx, edx
  2026 0000170B F7F3                    	div	ebx
  2027 0000170D 80C230                  	add	dl, 30h
  2028 00001710 8816                    	mov	[esi], dl
  2029 00001712 FEC9                    	dec	cl
  2030 00001714 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2031 00001716 09C0                    	or	eax, eax
  2032 00001718 75EE                    	jnz	short btdstr0
  2033                                  btdstr1:
  2034 0000171A 4E                      	dec	esi
  2035 0000171B C60620                          mov     byte [esi], 20h ; blank space
  2036 0000171E FEC9                    	dec	cl
  2037 00001720 75F8                    	jnz	short btdstr1
  2038                                  btdstr2:
  2039 00001722 C3                      	retn
  2040                                  
  2041                                  ; Calculate free memory pages on M.A.T.
  2042                                  ; 06/11/2014
  2043                                  ; Temporary Code
  2044                                  ;
  2045                                  
  2046                                  calc_free_mem:
  2047 00001723 31D2                    	xor	edx, edx
  2048                                  	;xor	ecx, ecx
  2049                                  	;mov	cx, [mat_size] ; in pages
  2050                                  	; 02/01/2022
  2051 00001725 8B0D[A06F0000]          	mov	ecx, [mat_size] ; in pages
  2052 0000172B C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2053 0000172E BE00001000              	mov	esi, MEM_ALLOC_TBL
  2054                                  cfm0:
  2055 00001733 AD                      	lodsd
  2056 00001734 51                      	push	ecx
  2057 00001735 B920000000              	mov	ecx, 32
  2058                                  cfm1:
  2059 0000173A D1E8                    	shr	eax, 1
  2060 0000173C 7301                    	jnc	short cfm2
  2061 0000173E 42                      	inc	edx
  2062                                  cfm2:
  2063 0000173F E2F9                    	loop	cfm1
  2064 00001741 59                      	pop	ecx
  2065 00001742 E2EF                    	loop	cfm0
  2066 00001744 C3                      	retn
  2067                                  
  2068                                  %include 'diskio.s'  ; 07/03/2015
  2069                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2070                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2071                              <1> ; ****************************************************************************
  2072                              <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC
  2073                              <1> ; Last Modification: 05/12/2021
  2074                              <1> ;
  2075                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2076                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2077                              <1> 
  2078                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2079                              <1> 
  2080                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2081                              <1> 
  2082                              <1> ; 06/02/2015
  2083                              <1> diskette_io:
  2084 00001745 9C                  <1> 	pushfd
  2085 00001746 0E                  <1> 	push 	cs
  2086 00001747 E809000000          <1> 	call 	DISKETTE_IO_1
  2087 0000174C C3                  <1> 	retn
  2088                              <1> 	
  2089                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2090                              <1> ;//////////////////////////////////////////////////////
  2091                              <1> 
  2092                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2093                              <1> ; 20/02/2015
  2094                              <1> ; 06/02/2015 (unix386.s)
  2095                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2096                              <1> ;
  2097                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2098                              <1> ;
  2099                              <1> ; ADISK.EQU
  2100                              <1> 
  2101                              <1> ;----- Wait control constants 
  2102                              <1> 
  2103                              <1> ;amount of time to wait while RESET is active.
  2104                              <1> 
  2105                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2106                              <1> 					;at 250 KBS xfer rate.
  2107                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2108                              <1> 
  2109                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2110                              <1> 					;status register to become valid
  2111                              <1> 					;before re-reading.
  2112                              <1> 
  2113                              <1> ;After sending a byte to NEC, status register may remain
  2114                              <1> ;incorrectly set for 24 us.
  2115                              <1> 
  2116                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2117                              <1> 					;RQM low.
  2118                              <1> 
  2119                              <1> ; COMMON.MAC
  2120                              <1> ;
  2121                              <1> ;	Timing macros
  2122                              <1> ;
  2123                              <1> 
  2124                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2125                              <1> 		jmp short $+2
  2126                              <1> %endmacro		
  2127                              <1> 
  2128                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2129                              <1> 		jmp short $+2
  2130                              <1> 		jmp short $+2
  2131                              <1> %endmacro
  2132                              <1> 
  2133                              <1> %macro		NEWIODELAY 0
  2134                              <1> 		out	0EBh,al
  2135                              <1> %endmacro 
  2136                              <1> 
  2137                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2138                              <1> ;;; WAIT_FOR_MEM
  2139                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2140                              <1> ;WAIT_FDU_INT_HI	equ	1
  2141                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2142                              <1> ;;; WAIT_FOR_PORT
  2143                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2144                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2145                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2146                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2147                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2148                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2149                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2150                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2151                              <1> ;;; WAIT_REFRESH
  2152                              <1> ;amount of time to wait for head settle, per unit in parameter
  2153                              <1> ;table = 1 ms.
  2154                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2155                              <1> 
  2156                              <1> 
  2157                              <1> ; //////////////// DISKETTE I/O ////////////////
  2158                              <1> 
  2159                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2160                              <1> 
  2161                              <1> ;----------------------------------------
  2162                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2163                              <1> ;----------------------------------------
  2164                              <1> 
  2165                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2166                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2167                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2168                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2169                              <1> 
  2170                              <1> ;----------------------------------------
  2171                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2172                              <1> ;-------------------------------------------------------------------------------
  2173                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2174                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2175                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2176                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2177                              <1> 
  2178                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2179                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2180                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2181                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2182                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2183                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2184                              <1> 
  2185                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2186                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2187                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2188                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2189                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2190                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2191                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2192                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2193                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2194                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2195                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2196                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2197                              <1> 
  2198                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2199                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2200                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2201                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2202                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2203                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2204                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2205                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2206                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2207                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2208                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2209                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2210                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2211                              <1> 
  2212                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2213                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2214                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2215                              <1> 
  2216                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2217                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2218                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2219                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2220                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2221                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2222                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2223                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2224                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2225                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2226                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2227                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2228                              <1> 
  2229                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2230                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2231                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2232                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2233                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2234                              <1> 
  2235                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2236                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2237                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2238                              <1> INTA01		EQU	021H		; 8259 PORT
  2239                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2240                              <1> INTB01		EQU	0A1H		;
  2241                              <1> 
  2242                              <1> ;-------------------------------------------------------------------------------
  2243                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2244                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2245                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2246                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2247                              <1> ;-------------------------------------------------------------------------------
  2248                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2249                              <1> 
  2250                              <1> ;-------------------------------------------------------------------------------
  2251                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2252                              <1> 
  2253                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2254                              <1> ; (unix386.s <-- dsectrm2.s)
  2255                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2256                              <1> 
  2257                              <1> ; 10/12/2014
  2258                              <1> ;
  2259                              <1> ;int40h:
  2260                              <1> ;	pushf
  2261                              <1> ;	push 	cs
  2262                              <1> ;	;cli
  2263                              <1> ;	call 	DISKETTE_IO_1
  2264                              <1> ;	retn
  2265                              <1> 
  2266                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2267                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2268                              <1> ;
  2269                              <1> 
  2270                              <1> ;-- INT13H ---------------------------------------------------------------------
  2271                              <1> ; DISKETTE I/O
  2272                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2273                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2274                              <1> ; INPUT
  2275                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2276                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2277                              <1> ;		ON ALL DRIVES
  2278                              <1> ;------------------------------------------------------------------------------- 
  2279                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2280                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2281                              <1> ;-------------------------------------------------------------------------------
  2282                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2283                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2284                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2285                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2286                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2287                              <1> ;		320/360	320/360	    0-39
  2288                              <1> ;		320/360	1.2M	    0-39
  2289                              <1> ;		1.2M	1.2M	    0-79
  2290                              <1> ;		720K	720K	    0-79
  2291                              <1> ;		1.44M	1.44M	    0-79	
  2292                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2293                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2294                              <1> ;		320/360	320/360	     1-8/9
  2295                              <1> ;		320/360	1.2M	     1-8/9
  2296                              <1> ;		1.2M	1.2M	     1-15
  2297                              <1> ;		720K	720K	     1-9
  2298                              <1> ;		1.44M	1.44M	     1-18		
  2299                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2300                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2301                              <1> ;		320/360	320/360	        8/9
  2302                              <1> ;		320/360	1.2M	        8/9
  2303                              <1> ;		1.2M	1.2M		15
  2304                              <1> ;		720K	720K		9
  2305                              <1> ;		1.44M	1.44M		18
  2306                              <1> ;
  2307                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2308                              <1> ;
  2309                              <1> ;-------------------------------------------------------------------------------
  2310                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2311                              <1> ;-------------------------------------------------------------------------------
  2312                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2313                              <1> ;-------------------------------------------------------------------------------
  2314                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2315                              <1> ;-------------------------------------------------------------------------------
  2316                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2317                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2318                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2319                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2320                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2321                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2322                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2323                              <1> ;		READ/WRITE ACCESS.
  2324                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2325                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2326                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2327                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2328                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2329                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2330                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2331                              <1> ;
  2332                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2333                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2334                              <1> ;		---------------------------------------------
  2335                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2336                              <1> ;		---------------------------------------------
  2337                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2338                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2339                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2340                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2341                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2342                              <1> ;		---------------------------------------------
  2343                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2344                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2345                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2346                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2347                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2348                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2349                              <1> ;-------------------------------------------------------------------------------
  2350                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2351                              <1> ;	REGISTERS
  2352                              <1> ;	  INPUT
  2353                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2354                              <1> ;	  OUTPUT
  2355                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2356                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2357                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2358                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2359                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2360                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2361                              <1> ;	    (BH) - 0
  2362                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2363                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2364                              <1> ;	    (AX) - 0
  2365                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2366                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2367                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2368                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2369                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2370                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2371                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2372                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2373                              <1> ;-------------------------------------------------------------------------------
  2374                              <1> ;	(AH)= 15H  READ DASD TYPE
  2375                              <1> ;	OUTPUT REGISTERS
  2376                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2377                              <1> ;		00 - DRIVE NOT PRESENT	
  2378                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2379                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2380                              <1> ;		03 - RESERVED (FIXED DISK)
  2381                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2382                              <1> ;-------------------------------------------------------------------------------
  2383                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2384                              <1> ;	OUTPUT REGISTERS
  2385                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2386                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2387                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2388                              <1> ;-------------------------------------------------------------------------------
  2389                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2390                              <1> ;	INPUT REGISTERS
  2391                              <1> ;	(AL) -	00 - NOT USED	
  2392                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2393                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2394                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2395                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2396                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2397                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2398                              <1> ;-------------------------------------------------------------------------------
  2399                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2400                              <1> ;	INPUT REGISTERS
  2401                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2402                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2403                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2404                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2405                              <1> ;	OUTPUT REGISTERS:
  2406                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2407                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2408                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2409                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2410                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2411                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2412                              <1> ;-------------------------------------------------------------------------------
  2413                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2414                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2415                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2416                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2417                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2418                              <1> ;		CHANGE ERROR CODE
  2419                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2420                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2421                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2422                              <1> ;
  2423                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2424                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2425                              <1> ;-------------------------------------------------------------------------------
  2426                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2427                              <1> ;	AH = STATUS OF OPERATION
  2428                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2429                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2430                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2431                              <1> ;		TYPE AH=(15)).
  2432                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2433                              <1> ;	FOR READ/WRITE/VERIFY
  2434                              <1> ;		DS,BX,DX,CX PRESERVED
  2435                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2436                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2437                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2438                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2439                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2440                              <1> ;-------------------------------------------------------------------------------
  2441                              <1> ;
  2442                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2443                              <1> ;
  2444                              <1> ;   -----------------------------------------------------------------
  2445                              <1> ;   |       |       |       |       |       |       |       |       |
  2446                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2447                              <1> ;   |       |       |       |       |       |       |       |       |
  2448                              <1> ;   -----------------------------------------------------------------
  2449                              <1> ;	|	|	|	|	|	|	|	|
  2450                              <1> ;	|	|	|	|	|	-----------------
  2451                              <1> ;	|	|	|	|	|		|
  2452                              <1> ;	|	|	|	|    RESERVED		|
  2453                              <1> ;	|	|	|	|		  PRESENT STATE
  2454                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2455                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2456                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2457                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2458                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2459                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2460                              <1> ;	|	|	|	|	110: RESERVED
  2461                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2462                              <1> ;	|	|	|	|
  2463                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2464                              <1> ;	|	|	|
  2465                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2466                              <1> ;	|	|			DRIVE)
  2467                              <1> ;	|	|
  2468                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2469                              <1> ;
  2470                              <1> ;						00: 500 KBS
  2471                              <1> ;						01: 300 KBS
  2472                              <1> ;						10: 250 KBS
  2473                              <1> ;						11: RESERVED
  2474                              <1> ;
  2475                              <1> ;
  2476                              <1> ;-------------------------------------------------------------------------------
  2477                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2478                              <1> ;-------------------------------------------------------------------------------
  2479                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2480                              <1> ;-------------------------------------------------------------------------------
  2481                              <1> 
  2482                              <1> struc MD
  2483 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2484 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2485 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2486 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2487 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2488 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2489 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2490 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2491 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2492 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2493 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2494 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2495 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2496                              <1> endstruc
  2497                              <1> 
  2498                              <1> BIT7OFF	EQU	7FH
  2499                              <1> BIT7ON	EQU	80H
  2500                              <1> 
  2501                              <1> ;;int13h: ; 16/02/2015
  2502                              <1> ;; 16/02/2015 - 21/02/2015
  2503                              <1> int40h:
  2504 0000174D 9C                  <1> 	pushfd
  2505 0000174E 0E                  <1> 	push 	cs
  2506 0000174F E801000000          <1> 	call 	DISKETTE_IO_1
  2507 00001754 C3                  <1> 	retn	
  2508                              <1> 
  2509                              <1> DISKETTE_IO_1:
  2510                              <1> 
  2511 00001755 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2512 00001756 55                  <1> 	PUSH	eBP			; USER REGISTER
  2513 00001757 57                  <1> 	PUSH	eDI			; USER REGISTER
  2514 00001758 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2515 00001759 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2516 0000175A 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2517 0000175B 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2518                              <1> 					; [BP]   = SECTOR #
  2519                              <1> 					; [BP+1] = TRACK #
  2520                              <1> 					; [BP+2] = BUFFER OFFSET
  2521                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2522                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2523                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2524                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2525                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2526                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2527                              <1> 					; BH/[BP+3] = 0
  2528                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2529                              <1> 					; DH/[BP+5] = MAX HEAD #
  2530                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2531 0000175D 06                  <1> 	push	es ; 06/02/2015	
  2532 0000175E 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2533 0000175F 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2534                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2535                              <1> 	;mov	cx, cs
  2536                              <1> 	;mov	ds, cx
  2537 00001760 66B91000            <1> 	mov	cx, KDATA
  2538 00001764 8ED9                <1>         mov     ds, cx
  2539 00001766 8EC1                <1>         mov     es, cx
  2540                              <1> 
  2541                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2542 00001768 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2543 0000176B 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2544 0000176D B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2545                              <1> OK_FUNC:
  2546 0000176F 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2547 00001772 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2548 00001774 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2549 00001777 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2550 00001779 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2551 0000177C 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2552 0000177E B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2553                              <1> OK_DRV:
  2554 00001780 31C9                <1> 	xor	ecx, ecx
  2555                              <1> 	;mov	esi, ecx ; 08/02/2015
  2556                              <1> 	; 05/12/2021
  2557 00001782 89CE                <1> 	mov	esi, ecx
  2558 00001784 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2559 00001786 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2560                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2561                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2562 00001788 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2563 0000178B BB[C3170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2564 00001790 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2565 00001792 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2566 00001794 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2567 00001796 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2568 00001799 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2569                              <1> 	;
  2570                              <1> 	; 11/12/2014
  2571 0000179C 8815[716A0000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2572                              <1> 	;
  2573 000017A2 8A25[0C700000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2574 000017A8 C605[0C700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2575                              <1> 
  2576                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2577                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2578                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2579                              <1> ;
  2580                              <1> ;		DI	: DRIVE #
  2581                              <1> ;		SI-HI	: HEAD #
  2582                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2583                              <1> ;		ES	: BUFFER SEGMENT
  2584                              <1> ;		[BP]	: SECTOR #
  2585                              <1> ;		[BP+1]	: TRACK #
  2586                              <1> ;		[BP+2]	: BUFFER OFFSET
  2587                              <1> ;
  2588                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2589                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2590                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2591                              <1> ;	SPECIFIC ERROR CODE.
  2592                              <1> ;
  2593                              <1> 					; (AH) = @DSKETTE_STATUS
  2594 000017AF FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2595 000017B1 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2596 000017B2 1F                  <1> 	POP	DS
  2597 000017B3 07                  <1> 	pop	es	; 06/02/2015
  2598 000017B4 59                  <1> 	POP	eCX
  2599 000017B5 5B                  <1> 	POP	eBX
  2600 000017B6 5A                  <1> 	POP	eDX
  2601 000017B7 5F                  <1> 	POP	eDI
  2602 000017B8 89E5                <1> 	MOV	eBP, eSP
  2603 000017BA 50                  <1> 	PUSH	eAX
  2604 000017BB 9C                  <1> 	PUSHFd
  2605 000017BC 58                  <1> 	POP	eAX
  2606                              <1> 	;MOV	[BP+6], AX
  2607 000017BD 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2608 000017C0 58                  <1> 	POP	eAX
  2609 000017C1 5D                  <1> 	POP	eBP
  2610 000017C2 CF                  <1> 	IRETd
  2611                              <1> 
  2612                              <1> ;-------------------------------------------------------------------------------
  2613                              <1> ; DW --> dd (06/02/2015)
  2614 000017C3 [27180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2615 000017C7 [9C180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2616 000017CB [AC180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2617 000017CF [BD180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2618 000017D3 [CE180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2619 000017D7 [DF180000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2620 000017DB [63190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2621 000017DF [63190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2622 000017E3 [6F190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2623 000017E7 [63190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2624 000017EB [63190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2625 000017EF [63190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2626 000017F3 [63190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2627 000017F7 [63190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2628 000017FB [63190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2629 000017FF [63190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2630 00001803 [63190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2631 00001807 [63190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2632 0000180B [63190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2633 0000180F [63190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2634 00001813 [63190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2635 00001817 [2E1A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2636 0000181B [561A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2637 0000181F [8F1A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2638 00001823 [101B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2639                              <1> FNC_TAE EQU     $                       ; END
  2640                              <1> 
  2641                              <1> ;-------------------------------------------------------------------------------
  2642                              <1> ; DISK_RESET	(AH = 00H)	
  2643                              <1> ;		RESET THE DISKETTE SYSTEM.
  2644                              <1> ;
  2645                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2646                              <1> ;-------------------------------------------------------------------------------
  2647                              <1> DSK_RESET:
  2648 00001827 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2649 0000182B FA                  <1> 	CLI				; NO INTERRUPTS
  2650 0000182C A0[0A700000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2651 00001831 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2652 00001833 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2653                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2654 00001836 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2655 00001838 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2656 00001839 C605[09700000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2657                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2658                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2659                              <1> 					;      PULSE WIDTH)
  2660                              <1> 	; 19/12/2014
  2661                              <1> 	NEWIODELAY
  2134 00001840 E6EB                <2>  out 0EBh,al
  2662                              <1> 
  2663                              <1> 	; 17/12/2014 
  2664                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2665 00001842 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2666                              <1> wdw1:
  2667                              <1> 	NEWIODELAY   ; 27/02/2015
  2134 00001847 E6EB                <2>  out 0EBh,al
  2668 00001849 E2FC                <1> 	loop	wdw1
  2669                              <1> 	;
  2670 0000184B 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2671 0000184D EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2672                              <1> 	; 16/12/2014
  2673                              <1> 	IODELAY
  2129 0000184E EB00                <2>  jmp short $+2
  2130 00001850 EB00                <2>  jmp short $+2
  2674                              <1> 	;
  2675                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2676 00001852 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2677 00001857 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2678 00001859 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2679                              <1> NXT_DRV:
  2680                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2681                              <1> 	; 05/12/2021
  2682 0000185D 51                  <1> 	push	ecx
  2683 0000185E B8[92180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2684 00001863 50                  <1> 	PUSH	eAX			; "
  2685 00001864 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2686 00001866 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2687 0000186B 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2688 0000186C E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2689                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2690                              <1> 	; 05/12/2021
  2691 00001871 59                  <1> 	pop	ecx
  2692 00001872 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2693 00001874 3A0D[0D700000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2694 0000187A 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2695 0000187C FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2696 0000187E 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2697 00001881 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2698                              <1> 	;
  2699 00001883 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2700                              <1> RESBAC:
  2701 00001888 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2702                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2703                              <1> 	; 05/12/2021
  2704 0000188D 89F3                <1> 	mov	ebx, esi
  2705 0000188F 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2706 00001891 C3                  <1> 	RETn		
  2707                              <1> DR_POP_ERR:
  2708                              <1> 	;POP	CX			; CLEAR STACK
  2709                              <1> 	; 05/12/2021
  2710 00001892 59                  <1> 	pop	ecx
  2711                              <1> DR_ERR:
  2712 00001893 800D[0C700000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2713 0000189A EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2714                              <1> 
  2715                              <1> ;-------------------------------------------------------------------------------
  2716                              <1> ; DISK_STATUS	(AH = 01H)
  2717                              <1> ;	DISKETTE STATUS.
  2718                              <1> ;
  2719                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2720                              <1> ;
  2721                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2722                              <1> ;-------------------------------------------------------------------------------
  2723                              <1> DSK_STATUS:
  2724 0000189C 8825[0C700000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2725 000018A2 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2726                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2727                              <1> 	; 05/12/2021
  2728 000018A7 89F3                <1> 	mov	ebx, esi
  2729 000018A9 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2730 000018AB C3                  <1> 	RETn		
  2731                              <1> 
  2732                              <1> ;-------------------------------------------------------------------------------
  2733                              <1> ; DISK_READ	(AH = 02H)	
  2734                              <1> ;	DISKETTE READ.
  2735                              <1> ;
  2736                              <1> ; ON ENTRY:	DI	: DRIVE #
  2737                              <1> ;		SI-HI	: HEAD #
  2738                              <1> ;		SI-LOW	: # OF SECTORS
  2739                              <1> ;		ES	: BUFFER SEGMENT
  2740                              <1> ;		[BP]	: SECTOR #
  2741                              <1> ;		[BP+1]	: TRACK #
  2742                              <1> ;		[BP+2]	: BUFFER OFFSET
  2743                              <1> ;
  2744                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2745                              <1> ;-------------------------------------------------------------------------------
  2746                              <1> 
  2747                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2748                              <1> 
  2749                              <1> DSK_READ:
  2750 000018AC 8025[0A700000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2751 000018B3 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2752 000018B7 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2753 000018BC C3                  <1> 	RETn
  2754                              <1> 
  2755                              <1> ;-------------------------------------------------------------------------------
  2756                              <1> ; DISK_WRITE	(AH = 03H)
  2757                              <1> ;	DISKETTE WRITE.
  2758                              <1> ;
  2759                              <1> ; ON ENTRY:	DI	: DRIVE #
  2760                              <1> ;		SI-HI	: HEAD #
  2761                              <1> ;		SI-LOW	: # OF SECTORS
  2762                              <1> ;		ES	: BUFFER SEGMENT
  2763                              <1> ;		[BP]	: SECTOR #
  2764                              <1> ;		[BP+1]	: TRACK #
  2765                              <1> ;		[BP+2]	: BUFFER OFFSET
  2766                              <1> ;
  2767                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2768                              <1> ;-------------------------------------------------------------------------------
  2769                              <1> 
  2770                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2771                              <1> 
  2772                              <1> DSK_WRITE:
  2773 000018BD 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2774 000018C1 800D[0A700000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2775 000018C8 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2776 000018CD C3                  <1> 	RETn
  2777                              <1> 
  2778                              <1> ;-------------------------------------------------------------------------------
  2779                              <1> ; DISK_VERF	(AH = 04H)
  2780                              <1> ;	DISKETTE VERIFY.
  2781                              <1> ;
  2782                              <1> ; ON ENTRY:	DI	: DRIVE #
  2783                              <1> ;		SI-HI	: HEAD #
  2784                              <1> ;		SI-LOW	: # OF SECTORS
  2785                              <1> ;		ES	: BUFFER SEGMENT
  2786                              <1> ;		[BP]	: SECTOR #
  2787                              <1> ;		[BP+1]	: TRACK #
  2788                              <1> ;		[BP+2]	: BUFFER OFFSET
  2789                              <1> ;
  2790                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2791                              <1> ;-------------------------------------------------------------------------------
  2792                              <1> DSK_VERF:
  2793 000018CE 8025[0A700000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2794 000018D5 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2795 000018D9 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2796 000018DE C3                  <1> 	RETn
  2797                              <1> 
  2798                              <1> ;-------------------------------------------------------------------------------
  2799                              <1> ; DISK_FORMAT	(AH = 05H)
  2800                              <1> ;	DISKETTE FORMAT.
  2801                              <1> ;
  2802                              <1> ; ON ENTRY:	DI	: DRIVE #
  2803                              <1> ;		SI-HI	: HEAD #
  2804                              <1> ;		SI-LOW	: # OF SECTORS
  2805                              <1> ;		ES	: BUFFER SEGMENT
  2806                              <1> ;		[BP]	: SECTOR #
  2807                              <1> ;		[BP+1]	: TRACK #
  2808                              <1> ;		[BP+2]	: BUFFER OFFSET
  2809                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2810                              <1> ;
  2811                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2812                              <1> ;-------------------------------------------------------------------------------
  2813                              <1> DSK_FORMAT:
  2814 000018DF E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2815 000018E4 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2816 000018E9 800D[0A700000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2817 000018F0 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2818 000018F5 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2819 000018F7 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2820 000018FC E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2821 00001901 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2822 00001903 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2823                              <1> FM_WR:
  2824 00001908 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2825 0000190D 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2826 0000190F B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2827 00001911 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2828 00001916 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2829 00001918 B8[54190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2830 0000191D 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2831 0000191E B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2832 00001920 E80E090000          <1> 	CALL	GET_PARM
  2833 00001925 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2834 0000192A B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2835 0000192C E802090000          <1> 	CALL	GET_PARM
  2836 00001931 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2837 00001936 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2838 00001938 E8F6080000          <1> 	CALL	GET_PARM
  2839 0000193D E8F7090000          <1> 	CALL	NEC_OUTPUT
  2840 00001942 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2841 00001944 E8EA080000          <1> 	CALL	GET_PARM
  2842 00001949 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2843 0000194E 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2844 0000194F E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2845                              <1> FM_DON:
  2846 00001954 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2847 00001959 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2848                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2849 0000195E 89F3                <1> 	mov	ebx, esi ; 05/12/2021
  2850 00001960 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2851 00001962 C3                  <1> 	RETn
  2852                              <1> 
  2853                              <1> ;-------------------------------------------------------------------------------
  2854                              <1> ; FNC_ERR
  2855                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2856                              <1> ;	SET BAD COMMAND IN STATUS.
  2857                              <1> ;
  2858                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2859                              <1> ;-------------------------------------------------------------------------------
  2860                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2861                              <1> 	;MOV	AX,SI			; RESTORE AL
  2862                              <1> 	; 05/12/2021
  2863 00001963 89F0                <1> 	mov	eax, esi
  2864 00001965 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2865 00001967 8825[0C700000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2866 0000196D F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2867 0000196E C3                  <1> 	RETn
  2868                              <1> 
  2869                              <1> ;-------------------------------------------------------------------------------
  2870                              <1> ; DISK_PARMS	(AH = 08H)	
  2871                              <1> ;	READ DRIVE PARAMETERS.
  2872                              <1> ;
  2873                              <1> ; ON ENTRY:	DI : DRIVE #
  2874                              <1> ;
  2875                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2876                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2877                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2878                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2879                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2880                              <1> ;		BH/[BP+3] = 0
  2881                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2882                              <1> ;		DH/[BP+5] = MAX HEAD #
  2883                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2884                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2885                              <1> ;		AX        = 0
  2886                              <1> ;
  2887                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2888                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2889                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2890                              <1> ;		       CALLER.
  2891                              <1> ;-------------------------------------------------------------------------------
  2892                              <1> DSK_PARMS:
  2893 0000196F E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2894                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2895 00001974 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2896 00001976 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2897                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2898                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2899                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2900                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2901                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2902                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2903                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2904                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2905                              <1> 	;sub	edx, edx
  2906 00001979 66A1[7E6A0000]      <1> 	mov     ax, [fd0_type]
  2907 0000197F 6621C0              <1> 	and     ax, ax
  2908 00001982 7473                <1> 	jz      short NON_DRV
  2909 00001984 FEC2                <1> 	inc     dl
  2910 00001986 20E4                <1> 	and     ah, ah
  2911 00001988 7402                <1> 	jz      short STO_DL
  2912 0000198A FEC2                <1> 	inc     dl
  2913                              <1> STO_DL:
  2914                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2915 0000198C 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2916 0000198F 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2917 00001993 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2918                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2919 00001995 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2920 00001999 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2921                              <1> 	;;20/02/2015
  2922                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2923                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2924 0000199E 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2925 000019A0 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2926 000019A5 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2927                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2928 000019A7 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2929 000019AA 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2930 000019AD 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2931 000019B0 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2932                              <1> CHK_EST:
  2933 000019B2 8AA7[19700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2934 000019B8 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2935 000019BB 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2936                              <1> USE_EST:
  2937 000019BD 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2938 000019C0 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2939 000019C3 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2940                              <1> 
  2941                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2942                              <1> 
  2943 000019C5 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2944 000019C7 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2945 000019CC 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2946 000019CF 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2947 000019D2 F687[19700000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2948 000019D9 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2949                              <1> 
  2950                              <1> ;-----	IT IS 1.44 MB DRIVE
  2951                              <1> 
  2952                              <1> PARM144:
  2953 000019DB B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2954 000019DD E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2955 000019E2 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2956 000019E5 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2957                              <1> STO_CX:
  2958 000019E8 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2959                              <1> ES_DI:
  2960                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2961 000019EB 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2962                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2963                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2964                              <1> DP_OUT:
  2965 000019EE E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2966                              <1> 	;XOR	AX,AX			; CLEAR
  2967                              <1> 	; 05/12/2021
  2968 000019F3 31C0                <1> 	xor	eax, eax
  2969 000019F5 F8                  <1> 	CLC
  2970 000019F6 C3                  <1> 	RETn
  2971                              <1> 
  2972                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2973                              <1> 
  2974                              <1> NON_DRV:
  2975                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2976 000019F7 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2977                              <1> NON_DRV1:
  2978 000019FA 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2979 000019FF 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2980                              <1> 
  2981                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2982                              <1> 	
  2983 00001A01 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2984                              <1> 	;MOV	AX,SI			; RESTORE AL
  2985 00001A06 89F0                <1> 	mov	eax, esi ; 05/12/2021
  2986 00001A08 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2987 00001A0A F9                  <1> 	STC
  2988 00001A0B C3                  <1> 	RETn
  2989                              <1> 
  2990                              <1> NON_DRV2:
  2991                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2992 00001A0C 31C0                <1> 	xor	eax, eax	
  2993 00001A0E 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2994                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2995 00001A12 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  2996                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  2997 00001A15 89450C              <1> 	mov	[ebp+12], eax
  2998                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2999 00001A18 EBD4                <1> 	JMP	SHORT DP_OUT
  3000                              <1> 
  3001                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  3002                              <1> 
  3003                              <1> USE_EST2:
  3004 00001A1A B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  3005 00001A1C E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3006 00001A21 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3007 00001A24 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  3008 00001A27 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3009 00001A2A 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  3010 00001A2C EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  3011                              <1> 
  3012                              <1> ;-------------------------------------------------------------------------------
  3013                              <1> ; DISK_TYPE (AH = 15H)	
  3014                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  3015                              <1> ;
  3016                              <1> ;  ON ENTRY:	DI = DRIVE #
  3017                              <1> ;
  3018                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  3019                              <1> ;-------------------------------------------------------------------------------
  3020                              <1> DSK_TYPE:
  3021 00001A2E E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3022 00001A33 8A87[19700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  3023 00001A39 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  3024 00001A3B 7415                <1> 	JZ	short NO_DRV
  3025 00001A3D B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3026 00001A3F A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3027 00001A41 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3028 00001A43 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3029                              <1> DT_BACK:
  3030                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3031 00001A45 50                  <1> 	push	eax ; 05/12/2021
  3032 00001A46 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3033                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3034 00001A4B 58                  <1> 	pop	eax ; 05/12/2021
  3035 00001A4C F8                  <1> 	CLC				; NO ERROR
  3036                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3037                              <1> 	; 05/12/2021
  3038 00001A4D 89F3                <1> 	mov	ebx, esi
  3039 00001A4F 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3040 00001A51 C3                  <1> 	RETn
  3041                              <1> NO_DRV:	
  3042 00001A52 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3043 00001A54 EBEF                <1> 	JMP	SHORT DT_BACK
  3044                              <1> 
  3045                              <1> ;-------------------------------------------------------------------------------
  3046                              <1> ; DISK_CHANGE	(AH = 16H)
  3047                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3048                              <1> ;
  3049                              <1> ; ON ENTRY:	DI = DRIVE #
  3050                              <1> ;
  3051                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3052                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3053                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3054                              <1> ;-------------------------------------------------------------------------------
  3055                              <1> DSK_CHANGE:
  3056 00001A56 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3057 00001A5B 8A87[19700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3058 00001A61 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3059 00001A63 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3060 00001A65 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3061 00001A67 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3062                              <1> DC0:
  3063 00001A69 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3064 00001A6E 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3065                              <1> 
  3066 00001A70 C605[0C700000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3067                              <1> 
  3068 00001A77 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3069 00001A7C E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3070                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3071                              <1> 	; 05/12/2021
  3072 00001A81 89F3                <1> 	mov	ebx, esi
  3073 00001A83 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3074 00001A85 C3                  <1> 	RETn
  3075                              <1> DC_NON:
  3076 00001A86 800D[0C700000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3077 00001A8D EBE8                <1> 	JMP	SHORT FINIS
  3078                              <1> 
  3079                              <1> ;-------------------------------------------------------------------------------
  3080                              <1> ; FORMAT_SET	(AH = 17H)
  3081                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3082                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3083                              <1> ;
  3084                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3085                              <1> ;		DI     = DRIVE #
  3086                              <1> ;
  3087                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3088                              <1> ;		AH = @DSKETTE_STATUS
  3089                              <1> ;		CY = 1 IF ERROR
  3090                              <1> ;-------------------------------------------------------------------------------
  3091                              <1> FORMAT_SET:
  3092 00001A8F E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3093                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3094                              <1> 	; 05/12/2021
  3095 00001A94 56                  <1> 	push	esi
  3096 00001A95 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3097 00001A98 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3098 00001A9A 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3099 00001A9D 80A7[19700000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3100 00001AA4 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3101 00001AA6 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3102 00001AA8 808F[19700000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3103 00001AAF EB48                <1> 	JMP	SHORT S0
  3104                              <1> NOT_320:
  3105 00001AB1 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3106 00001AB6 803D[0C700000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3107 00001ABD 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3108                              <1> S3:
  3109 00001ABF 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3110 00001AC1 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3111 00001AC3 808F[19700000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3112 00001ACA EB2D                <1> 	JMP	SHORT S0
  3113                              <1> NOT_320_12:
  3114 00001ACC 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3115 00001ACE 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3116 00001AD0 808F[19700000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3117 00001AD7 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3118                              <1> NOT_12:	
  3119 00001AD9 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3120 00001ADB 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3121                              <1> 
  3122 00001ADD F687[19700000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3123 00001AE4 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3124 00001AE6 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3125 00001AE8 F687[19700000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3126 00001AEF 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3127                              <1> ASSUME:
  3128 00001AF1 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3129                              <1> OR_IT_IN:
  3130 00001AF3 0887[19700000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3131                              <1> S0:
  3132 00001AF9 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3133 00001AFE E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3134                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3135                              <1> 	; 05/12/2021
  3136 00001B03 5B                  <1> 	pop	ebx
  3137 00001B04 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3138 00001B06 C3                  <1> 	RETn
  3139                              <1> FS_ERR:
  3140 00001B07 C605[0C700000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3141 00001B0E EBE9                <1> 	JMP	SHORT S0
  3142                              <1> 
  3143                              <1> ;-------------------------------------------------------------------------------
  3144                              <1> ; SET_MEDIA	(AH = 18H)
  3145                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3146                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3147                              <1> ;
  3148                              <1> ; ON ENTRY:
  3149                              <1> ;	[BP]	= SECTOR PER TRACK
  3150                              <1> ;	[BP+1]	= TRACK #
  3151                              <1> ;	DI	= DRIVE #
  3152                              <1> ;
  3153                              <1> ; ON EXIT:
  3154                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3155                              <1> ;	IF NO ERROR:
  3156                              <1> ;		AH = 0
  3157                              <1> ;		CY = 0
  3158                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3159                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3160                              <1> ;	IF ERROR:	
  3161                              <1> ;		AH = @DSKETTE_STATUS
  3162                              <1> ;		CY = 1
  3163                              <1> ;-------------------------------------------------------------------------------
  3164                              <1> SET_MEDIA:
  3165 00001B10 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3166 00001B15 F687[19700000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3167 00001B1C 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3168 00001B1E E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3169 00001B23 803D[0C700000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3170 00001B2A 746B                <1> 	JE	short SM_RTN
  3171 00001B2C C605[0C700000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3172                              <1> SM_CMOS:
  3173 00001B33 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3174                              <1> 	;;20/02/2015
  3175                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3176                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3177 00001B38 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3178 00001B3A E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3179 00001B3F 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3180 00001B41 57                  <1> 	PUSH	eDI			; SAVE REG.
  3181 00001B42 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3182 00001B44 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3183                              <1> DR_SEARCH:
  3184 00001B49 8AA3[FC690000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3185 00001B4F 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3186 00001B52 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3187 00001B54 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3188                              <1> DR_FND:
  3189 00001B56 8BBB[FD690000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3190                              <1> MD_SEARCH:
  3191 00001B5C 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3192 00001B5F 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3193 00001B62 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3194 00001B64 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3195 00001B67 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3196 00001B6A 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3197                              <1> NXT_MD:
  3198                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3199 00001B6C 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3200 00001B6F E2D8                <1> 	LOOP    DR_SEARCH
  3201 00001B71 5F                  <1> 	POP	eDI			; RESTORE REG.
  3202                              <1> MD_NOT_FND:
  3203 00001B72 C605[0C700000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3204 00001B79 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3205                              <1> MD_FND:
  3206 00001B7B 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3207 00001B7E 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3208 00001B80 7502                <1> 	JNE	short MD_SET
  3209 00001B82 0C20                <1> 	OR	AL,DBL_STEP
  3210                              <1> MD_SET:
  3211                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3212 00001B84 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3213 00001B87 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3214 00001B89 5F                  <1> 	POP	eDI
  3215 00001B8A 80A7[19700000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3216 00001B91 0887[19700000]      <1> 	OR	[DSK_STATE+eDI], AL
  3217                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3218                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3219                              <1> SM_RTN:
  3220 00001B97 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3221 00001B9C E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3222 00001BA1 C3                  <1> 	RETn
  3223                              <1> 
  3224                              <1> ;----------------------------------------------------------------
  3225                              <1> ; DR_TYPE_CHECK							:
  3226                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3227                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3228                              <1> ; ON ENTRY:							:
  3229                              <1> ;	AL = DRIVE TYPE						:
  3230                              <1> ; ON EXIT:							:
  3231                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3232                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3233                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3234                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3235                              <1> ; REGISTERS ALTERED: eBX						:
  3236                              <1> ;----------------------------------------------------------------		
  3237                              <1> DR_TYPE_CHECK:
  3238                              <1> 	;PUSH	AX			
  3239                              <1> 	; 05/12/2021
  3240 00001BA2 50                  <1> 	push	eax
  3241 00001BA3 51                  <1> 	PUSH	eCX
  3242 00001BA4 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3243 00001BA6 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3244                              <1> TYPE_CHK:	
  3245 00001BAB 8AA3[FC690000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3246 00001BB1 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3247 00001BB3 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3248                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3249 00001BB5 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3250 00001BB8 E2F1                <1> 	LOOP    TYPE_CHK
  3251                              <1> 	;
  3252 00001BBA BB[5B6A0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3253                              <1> 					; Default for GET_PARM (11/12/2014)
  3254                              <1> 	;
  3255 00001BBF F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3256 00001BC0 EB06                <1> 	JMP	SHORT TYPE_RTN
  3257                              <1> DR_TYPE_VALID:
  3258 00001BC2 8B9B[FD690000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3259                              <1> TYPE_RTN:
  3260 00001BC8 59                  <1> 	POP	eCX
  3261                              <1> 	;POP	AX
  3262                              <1> 	; 05/12/2021
  3263 00001BC9 58                  <1> 	pop	eax
  3264 00001BCA C3                  <1> 	RETn	
  3265                              <1> 		
  3266                              <1> ;----------------------------------------------------------------
  3267                              <1> ; SEND_SPEC							:
  3268                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3269                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3270                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3271                              <1> ; ON EXIT:	NONE						:	
  3272                              <1> ; REGISTERS ALTERED: CX, DX					:
  3273                              <1> ;----------------------------------------------------------------		
  3274                              <1> SEND_SPEC:
  3275 00001BCB 50                  <1> 	PUSH	eAX			; SAVE AX
  3276 00001BCC B8[F21B0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3277 00001BD1 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3278 00001BD2 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3279 00001BD4 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3280 00001BD9 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3281 00001BDB E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3282 00001BE0 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3283 00001BE5 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3284 00001BE7 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3285 00001BEC E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3286 00001BF1 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3287                              <1> SPECBAC:
  3288 00001BF2 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3289 00001BF3 C3                  <1> 	RETn
  3290                              <1> 
  3291                              <1> ;----------------------------------------------------------------
  3292                              <1> ; SEND_SPEC_MD							:
  3293                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3294                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3295                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3296                              <1> ; ON EXIT:	NONE						:	
  3297                              <1> ; REGISTERS ALTERED: AX						:
  3298                              <1> ;----------------------------------------------------------------		
  3299                              <1> SEND_SPEC_MD:
  3300 00001BF4 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3301 00001BF5 B8[121C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3302 00001BFA 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3303 00001BFB B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3304 00001BFD E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3305 00001C02 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3306 00001C04 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3307 00001C09 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3308 00001C0C E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3309 00001C11 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3310                              <1> SPEC_ESBAC:
  3311 00001C12 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3312 00001C13 C3                  <1> 	RETn
  3313                              <1> 
  3314                              <1> ;-------------------------------------------------------------------------------
  3315                              <1> ; XLAT_NEW  
  3316                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3317                              <1> ;	MODE TO NEW ARCHITECTURE.
  3318                              <1> ;
  3319                              <1> ; ON ENTRY:	DI = DRIVE #
  3320                              <1> ;-------------------------------------------------------------------------------
  3321                              <1> XLAT_NEW:
  3322 00001C14 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3323 00001C17 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3324 00001C19 80BF[19700000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3325 00001C20 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3326 00001C22 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3327 00001C25 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3328 00001C28 A0[18700000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3329 00001C2D D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3330 00001C2F 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3331 00001C31 80A7[19700000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3332 00001C38 0887[19700000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3333                              <1> XN_OUT:
  3334 00001C3E C3                  <1> 	RETn
  3335                              <1> DO_DET:
  3336 00001C3F E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3337 00001C44 C3                  <1> 	RETn
  3338                              <1> 
  3339                              <1> ;-------------------------------------------------------------------------------
  3340                              <1> ; XLAT_OLD 
  3341                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3342                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3343                              <1> ;
  3344                              <1> ; ON ENTRY:	DI = DRIVE
  3345                              <1> ;-------------------------------------------------------------------------------
  3346                              <1> XLAT_OLD:
  3347 00001C45 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3348                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3349                              <1>         ;ja	XO_OUT
  3350                              <1>         ; 05/12/2021
  3351 00001C48 77F4                <1> 	ja	short XN_OUT
  3352 00001C4A 80BF[19700000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3353 00001C51 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3354                              <1> 
  3355                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3356                              <1> 
  3357 00001C53 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3358 00001C56 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3359 00001C59 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3360 00001C5B D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3361 00001C5D 8425[18700000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3362 00001C63 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3363                              <1> 
  3364                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3365                              <1> 
  3366 00001C65 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3367 00001C67 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3368 00001C69 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3369 00001C6B 2025[18700000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3370                              <1> 
  3371                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3372                              <1> 
  3373 00001C71 8A87[19700000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3374 00001C77 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3375 00001C79 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3376 00001C7B 0805[18700000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3377                              <1> 
  3378                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3379                              <1> 
  3380                              <1> SAVE_SET:
  3381 00001C81 8AA7[19700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3382 00001C87 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3383 00001C89 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3384 00001C8C 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3385 00001C8F 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3386 00001C91 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3387 00001C93 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3388 00001C96 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3389 00001C98 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3390 00001C9B 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3391                              <1> UNKNO:
  3392 00001C9D B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3393 00001C9F EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3394                              <1> CHK_144:
  3395 00001CA1 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3396                              <1> 	;;20/02/2015
  3397                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3398 00001CA6 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3399 00001CA8 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3400 00001CAA 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3401 00001CAC B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3402 00001CAE EB0C                <1> 	JMP	SHORT TST_DET
  3403                              <1> CHK_250:
  3404 00001CB0 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3405 00001CB2 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3406 00001CB5 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3407 00001CB7 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3408 00001CBA 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3409                              <1> TST_DET:
  3410 00001CBC F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3411 00001CBF 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3412 00001CC1 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3413                              <1> AL_SET:
  3414 00001CC3 80A7[19700000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3415 00001CCA 0887[19700000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3416                              <1> XO_OUT:
  3417 00001CD0 C3                  <1> 	RETn
  3418                              <1> 
  3419                              <1> ;-------------------------------------------------------------------------------
  3420                              <1> ; RD_WR_VF
  3421                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3422                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3423                              <1> ;
  3424                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3425                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3426                              <1> ;
  3427                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3428                              <1> ;-------------------------------------------------------------------------------
  3429                              <1> RD_WR_VF:
  3430                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3431 00001CD1 50                  <1> 	push	eax ; 05/12/2021
  3432 00001CD2 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3433 00001CD7 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3434                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3435 00001CDC 58                  <1> 	pop	eax ; 05/12/2021
  3436                              <1> DO_AGAIN:
  3437                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3438 00001CDD 50                  <1> 	push	eax ; 05/12/2021
  3439 00001CDE E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3440                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3441 00001CE3 58                  <1> 	pop	eax ; 05/12/2021
  3442                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3443                              <1> 	; 05/12/2021
  3444 00001CE4 7305                <1> 	jnc	short RWV
  3445 00001CE6 E9C3000000          <1> 	jmp	RWV_END
  3446                              <1> RWV:
  3447                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3448 00001CEB 50                  <1> 	push	eax ; 05/12/2021
  3449 00001CEC 8AB7[19700000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3450 00001CF2 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3451 00001CF5 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3452                              <1> 	;;20/02/2015
  3453                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3454 00001CFA 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3455 00001CFC 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3456 00001CFE 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3457 00001D00 F687[19700000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3458 00001D07 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3459 00001D09 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3460 00001D0B EB0F                <1> 	JMP	SHORT RWV_2
  3461                              <1> RWV_1:
  3462 00001D0D 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3463 00001D0F F687[19700000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3464 00001D16 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3465 00001D18 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3466 00001D1A EB04                <1> 	jmp	short rwv_3
  3467                              <1> RWV_2:
  3468 00001D1C 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3469 00001D1E 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3470                              <1> rwv_3:
  3471 00001D20 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3472 00001D25 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3473                              <1> 
  3474                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3475                              <1> 
  3476 00001D27 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3477 00001D28 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3478 00001D2A B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3479                              <1> RWV_DR_SEARCH:
  3480 00001D2F 8AA3[FC690000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3481 00001D35 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3482 00001D38 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3483 00001D3A 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3484                              <1> RWV_DR_FND:
  3485 00001D3C 8BBB[FD690000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3486                              <1> RWV_MD_SEARH:
  3487 00001D42 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3488 00001D45 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3489                              <1> RWV_NXT_MD:
  3490                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3491 00001D47 83C305              <1> 	add	eBX, 5
  3492 00001D4A E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3493 00001D4C 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3494                              <1> 
  3495                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3496                              <1> 
  3497                              <1> RWV_ASSUME:
  3498 00001D4D BB[1A6A0000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3499 00001D52 F687[19700000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3500 00001D59 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3501 00001D5B BB[346A0000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3502 00001D60 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3503                              <1> 
  3504                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3505                              <1> 	 			
  3506                              <1> RWV_MD_FND:
  3507 00001D62 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3508 00001D64 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3509                              <1> 	
  3510                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3511                              <1> 
  3512                              <1> RWV_MD_FND1:
  3513 00001D65 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3514 00001D6A E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3515 00001D6F 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3516 00001D71 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3517                              <1> RWV_DBL:
  3518 00001D76 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3519 00001D77 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3520 00001D7C 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3521 00001D7D 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3522                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3523 00001D7F 58                  <1> 	pop	eax ; 05/12/2021
  3524                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3525 00001D80 50                  <1> 	push	eax ; 05/12/2021
  3526 00001D81 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3527 00001D82 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3528 00001D87 5B                  <1> 	POP	eBX 
  3529                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3530 00001D88 58                  <1> 	pop	eax ; 05/12/2021
  3531 00001D89 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3532                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3533 00001D8B 50                  <1> 	push	eax ; 05/12/2021
  3534 00001D8C 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3535 00001D8D E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3536 00001D92 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3537 00001D93 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3538 00001D95 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3539 00001D9A 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3540 00001D9C E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3541                              <1> CHK_RET:
  3542 00001DA1 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3543                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3544 00001DA6 58                  <1> 	pop	eax ; 05/12/2021
  3545 00001DA7 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3546 00001DA9 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3547                              <1> RWV_END:
  3548 00001DAE E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3549 00001DB3 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3550                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3551                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3552 00001DB8 50                  <1> 	push	eax ; 05/12/2021
  3553 00001DB9 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3554                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3555 00001DBE 58                  <1> 	pop	eax ; 05/12/2021
  3556 00001DBF E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3557 00001DC4 C3                  <1> 	RETn
  3558                              <1> 
  3559                              <1> ;-------------------------------------------------------------------------------
  3560                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3561                              <1> ;-------------------------------------------------------------------------------
  3562                              <1> SETUP_STATE:
  3563 00001DC5 F687[19700000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3564 00001DCC 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3565 00001DCE 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3566 00001DD2 F687[19700000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3567 00001DD9 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3568 00001DDB F687[19700000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3569 00001DE2 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3570 00001DE4 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3571                              <1> AX_SET:	
  3572 00001DE8 80A7[19700000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3573 00001DEF 08A7[19700000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3574 00001DF5 8025[14700000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3575 00001DFC C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3576 00001DFF 0805[14700000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3577                              <1> J1C:	
  3578 00001E05 C3                  <1> 	RETn
  3579                              <1> 
  3580                              <1> ;-------------------------------------------------------------------------------
  3581                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3582                              <1> ;-------------------------------------------------------------------------------
  3583                              <1> FMT_INIT:
  3584 00001E06 F687[19700000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3585 00001E0D 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3586 00001E0F E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3587                              <1> 	;; 20/02/2015
  3588                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3589 00001E14 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3590 00001E16 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3591                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3592 00001E18 8AA7[19700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3593 00001E1E 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3594 00001E21 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3595 00001E23 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3596 00001E25 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3597 00001E28 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3598                              <1> N_360:	
  3599 00001E2A FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3600 00001E2C 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3601                              <1> F1_RATE:
  3602 00001E2E 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3603 00001E31 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3604                              <1> N_12:	
  3605 00001E33 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3606 00001E35 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3607 00001E37 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3608 00001E3A 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3609 00001E3C F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3610 00001E3F 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3611 00001E41 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3612 00001E44 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3613                              <1> N_720:
  3614 00001E46 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3615 00001E48 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3616 00001E4A EBE2                <1> 	JMP	SHORT F1_RATE
  3617                              <1> ISNT_12: 
  3618 00001E4C 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3619                              <1> 
  3620                              <1> SKP_STATE:
  3621 00001E4F 88A7[19700000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3622                              <1> F1_OUT:
  3623 00001E55 C3                  <1> 	RETn
  3624                              <1> CL_DRV:	
  3625 00001E56 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3626 00001E58 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3627                              <1> 
  3628                              <1> ;-------------------------------------------------------------------------------
  3629                              <1> ; MED_CHANGE	
  3630                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3631                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3632                              <1> ;
  3633                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3634                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3635                              <1> ;-------------------------------------------------------------------------------
  3636                              <1> MED_CHANGE:
  3637 00001E5A E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3638 00001E5F 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3639 00001E61 80A7[19700000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3640                              <1> 
  3641                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3642                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3643                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3644                              <1> 
  3645 00001E68 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3646 00001E6B B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3647 00001E6D D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3648 00001E6F F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3649 00001E71 FA                  <1> 	CLI				; NO INTERRUPTS
  3650 00001E72 2005[0A700000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3651 00001E78 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3652 00001E79 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3653                              <1> 
  3654                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3655                              <1> 
  3656 00001E7E E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3657 00001E83 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3658 00001E85 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3659 00001E8A 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3660 00001E8C E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3661 00001E91 C605[0C700000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3662                              <1> OK1:
  3663 00001E98 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3664 00001E9D 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3665                              <1> OK4:
  3666 00001E9F C605[0C700000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3667                              <1> OK2:		
  3668 00001EA6 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3669 00001EA7 C3                  <1> 	RETn
  3670                              <1> MC_OUT:
  3671 00001EA8 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3672 00001EA9 C3                  <1> 	RETn
  3673                              <1> 
  3674                              <1> ;-------------------------------------------------------------------------------
  3675                              <1> ; SEND_RATE
  3676                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3677                              <1> ; ON ENTRY:	DI = DRIVE #
  3678                              <1> ; ON EXIT:	NONE
  3679                              <1> ; REGISTERS ALTERED: DX
  3680                              <1> ;-------------------------------------------------------------------------------
  3681                              <1> SEND_RATE:
  3682                              <1> 	;PUSH	AX			; SAVE REG.
  3683                              <1> 	; 05/12/2021
  3684 00001EAA 50                  <1> 	push	eax
  3685 00001EAB 8025[14700000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3686 00001EB2 8A87[19700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3687 00001EB8 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3688 00001EBA 0805[14700000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3689 00001EC0 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3690 00001EC3 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3691 00001EC7 EE                  <1> 	OUT	DX,AL
  3692                              <1> 	;POP	AX			; RESTORE REG.
  3693                              <1> 	; 05/12/2021
  3694 00001EC8 58                  <1> 	pop	eax
  3695 00001EC9 C3                  <1> 	RETn
  3696                              <1> 
  3697                              <1> ;-------------------------------------------------------------------------------
  3698                              <1> ; CHK_LASTRATE
  3699                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3700                              <1> ; ON ENTRY:
  3701                              <1> ;	DI = DRIVE #
  3702                              <1> ; ON EXIT:
  3703                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3704                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3705                              <1> ; REGISTERS ALTERED: DX
  3706                              <1> ;-------------------------------------------------------------------------------
  3707                              <1> CHK_LASTRATE:
  3708                              <1> 	;PUSH	AX			; SAVE REG.
  3709                              <1> 	; 05/12/2021
  3710 00001ECA 50                  <1> 	push	eax
  3711 00001ECB 2225[14700000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3712 00001ED1 8A87[19700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3713 00001ED7 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3714 00001EDB 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3715                              <1> 					; ZF = 1 RATE IS THE SAME
  3716                              <1> 	;POP	AX			; RESTORE REG.
  3717                              <1> 	; 05/12/2021
  3718 00001EDD 58                  <1> 	pop	eax
  3719 00001EDE C3                  <1> 	RETn
  3720                              <1> 
  3721                              <1> ;-------------------------------------------------------------------------------
  3722                              <1> ; DMA_SETUP
  3723                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3724                              <1> ;
  3725                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3726                              <1> ;
  3727                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3728                              <1> ;-------------------------------------------------------------------------------
  3729                              <1> 
  3730                              <1> ; SI = Head #, # of Sectors or DASD Type
  3731                              <1> 
  3732                              <1> ; 22/08/2015
  3733                              <1> ; 08/02/2015 - Protected Mode Modification
  3734                              <1> ; 06/02/2015 - 07/02/2015
  3735                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3736                              <1> ; (DMA Addres = Physical Address)
  3737                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3738                              <1> ;
  3739                              <1> ; 04/02/2016 (clc)
  3740                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3741                              <1> ; 16/12/2014 (IODELAY)
  3742                              <1> 
  3743                              <1> DMA_SETUP:
  3744                              <1> 
  3745                              <1> ;; 20/02/2015
  3746 00001EDF 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3747 00001EE2 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3748 00001EE8 7569                <1> 	jnz	short dma_bnd_err_stc
  3749                              <1> 	;
  3750                              <1> 	;push	ax			; DMA command
  3751                              <1> 	; 05/12/2021
  3752 00001EEA 50                  <1> 	push	eax
  3753 00001EEB 52                  <1> 	push	edx			; *
  3754 00001EEC B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3755 00001EEE E840030000          <1> 	call	GET_PARM		; 
  3756 00001EF3 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3757                              <1> 	;mov	ax, si			; Sector count
  3758                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3759                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3760                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3761                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3762                              <1> 	; 05/12/2021
  3763 00001EF5 89F2                <1> 	mov	edx, esi
  3764 00001EF7 29C0                <1> 	sub	eax, eax
  3765 00001EF9 88D4                <1> 	mov	ah, dl
  3766 00001EFB D1E8                <1> 	shr	eax, 1
  3767 00001EFD D3E0                <1> 	shl	eax, cl
  3768                              <1> 	;
  3769 00001EFF 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3770 00001F01 6689C1              <1> 	mov	cx, ax
  3771 00001F04 5A                  <1> 	pop	edx			; *
  3772                              <1> 	;pop	ax
  3773                              <1> 	; 05/12/2021
  3774 00001F05 58                  <1> 	pop	eax
  3775 00001F06 3C42                <1> 	cmp	al, 42h
  3776 00001F08 7507                <1>         jne     short NOT_VERF
  3777 00001F0A BA0000FF00          <1> 	mov	edx, 0FF0000h
  3778 00001F0F EB08                <1> 	jmp	short J33
  3779                              <1> NOT_VERF:
  3780 00001F11 6601CA              <1> 	add	dx, cx			; check for overflow
  3781 00001F14 723E                <1> 	jc	short dma_bnd_err
  3782                              <1> 	;
  3783 00001F16 6629CA              <1> 	sub	dx, cx			; Restore start address
  3784                              <1> J33:
  3785 00001F19 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3786 00001F1A E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3787                              <1> 	IODELAY				; WAIT FOR I/O
  2129 00001F1C EB00                <2>  jmp short $+2
  2130 00001F1E EB00                <2>  jmp short $+2
  3788 00001F20 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3789 00001F22 89D0                <1> 	mov	eax,edx			; Buffer address
  3790 00001F24 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3791                              <1> 	IODELAY				; WAIT FOR I/O
  2129 00001F26 EB00                <2>  jmp short $+2
  2130 00001F28 EB00                <2>  jmp short $+2
  3792 00001F2A 88E0                <1> 	MOV	AL,AH
  3793 00001F2C E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3794 00001F2E C1E810              <1> 	shr	eax,16
  3795                              <1> 	IODELAY				; I/O WAIT STATE
  2129 00001F31 EB00                <2>  jmp short $+2
  2130 00001F33 EB00                <2>  jmp short $+2
  3796 00001F35 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3797                              <1> 	IODELAY
  2129 00001F37 EB00                <2>  jmp short $+2
  2130 00001F39 EB00                <2>  jmp short $+2
  3798 00001F3B 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3799 00001F3E E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3800                              <1> 	IODELAY				; WAIT FOR I/O
  2129 00001F40 EB00                <2>  jmp short $+2
  2130 00001F42 EB00                <2>  jmp short $+2
  3801 00001F44 88E0                <1> 	MOV	AL,AH
  3802 00001F46 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3803                              <1> 	IODELAY
  2129 00001F48 EB00                <2>  jmp short $+2
  2130 00001F4A EB00                <2>  jmp short $+2
  3804 00001F4C FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3805 00001F4D B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3806 00001F4F E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3807                              <1> 
  3808 00001F51 F8                  <1> 	clc	; 04/02/2016
  3809 00001F52 C3                  <1> 	retn
  3810                              <1> 
  3811                              <1> dma_bnd_err_stc:
  3812 00001F53 F9                  <1> 	stc
  3813                              <1> dma_bnd_err:
  3814 00001F54 C605[0C700000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3815 00001F5B C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3816                              <1> 
  3817                              <1> ;; 16/12/2014
  3818                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3819                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3820                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3821                              <1> ;;	IODELAY
  3822                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3823                              <1> ;;	;SIODELAY
  3824                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3825                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3826                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3827                              <1> ;;      ;JMP	SHORT J33
  3828                              <1> ;;;NOT_VERF:	
  3829                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3830                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3831                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3832                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3833                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3834                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3835                              <1> ;;	;JNC	short J33
  3836                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3837                              <1> ;;;J33:
  3838                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3839                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3840                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3841                              <1> ;;	IODELAY
  3842                              <1> ;;	MOV	AL,AH
  3843                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3844                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3845                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3846                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3847                              <1> ;;	IODELAY
  3848                              <1> ;;	;AND	AL,00001111B
  3849                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3850                              <1> ;;	;SIODELAY
  3851                              <1> ;;
  3852                              <1> ;;;----- DETERMINE COUNT
  3853                              <1> ;;	sub	eax, eax ; 08/02/2015
  3854                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3855                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3856                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3857                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3858                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3859                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3860                              <1> ;;	CALL	GET_PARM		; "
  3861                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3862                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3863                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3864                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3865                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3866                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3867                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3868                              <1> ;;	IODELAY
  3869                              <1> ;;	MOV	AL, AH
  3870                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3871                              <1> ;;	;IODELAY
  3872                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3873                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3874                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3875                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3876                              <1> ;;	add	ecx, eax ; 08/02/2015
  3877                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3878                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3879                              <1> ;;	SIODELAY
  3880                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3881                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3882                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3883                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3884                              <1> ;;	jz	short NO_BAD
  3885                              <1> ;;dma_bnd_err:
  3886                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3887                              <1> ;;NO_BAD:
  3888                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3889                              <1> 
  3890                              <1> ;-------------------------------------------------------------------------------
  3891                              <1> ; FMTDMA_SET
  3892                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3893                              <1> ;
  3894                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3895                              <1> ;
  3896                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3897                              <1> ;-------------------------------------------------------------------------------
  3898                              <1> 
  3899                              <1> 	; 05/12/2021
  3900                              <1> FMTDMA_SET:
  3901                              <1> ;; 20/02/2015 modification	
  3902 00001F5C 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3903 00001F5F F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3904 00001F65 75EC                <1> 	jnz	short dma_bnd_err_stc
  3905                              <1> 	;
  3906                              <1> 	;push	dx			; *
  3907                              <1> 	; 05/12/2021
  3908 00001F67 52                  <1> 	push	edx
  3909 00001F68 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3910 00001F6A E8C4020000          <1> 	call	GET_PARM		; "
  3911                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3912                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3913                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3914                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3915                              <1> 	;mov	cx, ax
  3916                              <1> 	; 05/12/2021
  3917 00001F6F 29C9                <1> 	sub	ecx, ecx
  3918 00001F71 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3919 00001F73 D1E1                <1> 	shl	ecx, 1
  3920 00001F75 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3921 00001F77 6649                <1> 	dec	cx
  3922                              <1> 	;pop	dx			; *
  3923                              <1> 	; 05/12/2021
  3924 00001F79 5A                  <1> 	pop	edx
  3925 00001F7A 6601CA              <1> 	add	dx, cx			; check for overflow
  3926 00001F7D 72D5                <1> 	jc	short dma_bnd_err
  3927                              <1> 	;
  3928 00001F7F 6629CA              <1> 	sub	dx, cx			; Restore start address
  3929                              <1> 	;
  3930 00001F82 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3931 00001F84 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3932 00001F85 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3933                              <1> 	IODELAY				; WAIT FOR I/O
  2129 00001F87 EB00                <2>  jmp short $+2
  2130 00001F89 EB00                <2>  jmp short $+2
  3934 00001F8B E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3935 00001F8D 89D0                <1> 	mov	eax,edx			; Buffer address
  3936 00001F8F E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3937                              <1> 	IODELAY				; WAIT FOR I/O
  2129 00001F91 EB00                <2>  jmp short $+2
  2130 00001F93 EB00                <2>  jmp short $+2
  3938 00001F95 88E0                <1> 	MOV	AL,AH
  3939 00001F97 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3940 00001F99 C1E810              <1> 	shr	eax,16
  3941                              <1> 	IODELAY				; I/O WAIT STATE
  2129 00001F9C EB00                <2>  jmp short $+2
  2130 00001F9E EB00                <2>  jmp short $+2
  3942 00001FA0 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3943                              <1> 	IODELAY
  2129 00001FA2 EB00                <2>  jmp short $+2
  2130 00001FA4 EB00                <2>  jmp short $+2
  3944 00001FA6 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3945 00001FA9 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3946                              <1> 	IODELAY				; WAIT FOR I/O
  2129 00001FAB EB00                <2>  jmp short $+2
  2130 00001FAD EB00                <2>  jmp short $+2
  3947 00001FAF 88E0                <1> 	MOV	AL,AH
  3948 00001FB1 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3949                              <1> 	IODELAY
  2129 00001FB3 EB00                <2>  jmp short $+2
  2130 00001FB5 EB00                <2>  jmp short $+2
  3950 00001FB7 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3951 00001FB8 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3952 00001FBA E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3953 00001FBC C3                  <1> 	retn
  3954                              <1> 
  3955                              <1> ;; 08/02/2015 - Protected Mode Modification
  3956                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3957                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3958                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3959                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3960                              <1> ;;	IODELAY
  3961                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3962                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3963                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3964                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3965                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3966                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3967                              <1> ;;	;JNC	short J33A
  3968                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3969                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3970                              <1> ;;;J33A:
  3971                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3972                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3973                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3974                              <1> ;;	IODELAY
  3975                              <1> ;;	MOV	AL,AH
  3976                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3977                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3978                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3979                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3980                              <1> ;;	IODELAY
  3981                              <1> ;;	;AND	AL,00001111B
  3982                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3983                              <1> ;;
  3984                              <1> ;;;----- DETERMINE COUNT
  3985                              <1> ;;	sub	eax, eax ; 08/02/2015
  3986                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3987                              <1> ;;	CALL	GET_PARM		; "
  3988                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3989                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3990                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3991                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3992                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3993                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3994                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3995                              <1> ;;	IODELAY
  3996                              <1> ;;	MOV	AL, AH
  3997                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3998                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3999                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  4000                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  4001                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  4002                              <1> ;;	add	ecx, eax ; 08/02/2015
  4003                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  4004                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4005                              <1> ;;	SIODELAY
  4006                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  4007                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  4008                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  4009                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  4010                              <1> ;;	jz	short FMTDMA_OK
  4011                              <1> ;;	stc	; 20/02/2015
  4012                              <1> ;;fmtdma_bnd_err:
  4013                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  4014                              <1> ;;FMTDMA_OK:
  4015                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  4016                              <1> 
  4017                              <1> ;-------------------------------------------------------------------------------
  4018                              <1> ; NEC_INIT	
  4019                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  4020                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  4021                              <1> ;
  4022                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  4023                              <1> ;
  4024                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4025                              <1> ;-------------------------------------------------------------------------------
  4026                              <1> NEC_INIT:
  4027                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4028                              <1> 	; 05/12/2021
  4029 00001FBD 50                  <1> 	push	eax
  4030 00001FBE E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4031                              <1> 
  4032                              <1> ;-----	DO THE SEEK OPERATION
  4033                              <1> 
  4034 00001FC3 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4035 00001FC6 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4036                              <1> 	;POP	AX			; RECOVER COMMAND
  4037                              <1> 	; 05/12/2021
  4038 00001FCB 58                  <1> 	pop	eax
  4039 00001FCC 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4040 00001FCE BB[EC1F0000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4041 00001FD3 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4042                              <1> 
  4043                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4044                              <1> 
  4045 00001FD4 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4046 00001FD9 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4047 00001FDC 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4048 00001FDE C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4049 00001FE1 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4050 00001FE4 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4051 00001FE6 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4052 00001FEB 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4053                              <1> ER_1:
  4054 00001FEC C3                  <1> 	RETn
  4055                              <1> 
  4056                              <1> ;-------------------------------------------------------------------------------
  4057                              <1> ; RWV_COM
  4058                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4059                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4060                              <1> ;
  4061                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4062                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4063                              <1> ;-------------------------------------------------------------------------------
  4064                              <1> RWV_COM:
  4065 00001FED B8[38200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4066 00001FF2 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4067 00001FF3 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4068 00001FF6 E83E030000          <1> 	CALL	NEC_OUTPUT
  4069 00001FFB 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4070 00001FFE E836030000          <1> 	CALL	NEC_OUTPUT
  4071 00002003 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4072 00002006 E82E030000          <1> 	CALL	NEC_OUTPUT
  4073 0000200B B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4074 0000200D E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4075 00002012 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4076 00002017 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4077 00002019 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4078 0000201E E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4079 00002023 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4080                              <1> _R15:
  4081 00002026 E80E030000          <1> 	CALL	NEC_OUTPUT
  4082 0000202B B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4083 0000202D E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4084 00002032 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4085 00002037 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4086                              <1> ER_2:
  4087 00002038 C3                  <1> 	RETn
  4088                              <1> 
  4089                              <1> ;-------------------------------------------------------------------------------
  4090                              <1> ; NEC_TERM
  4091                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4092                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4093                              <1> ;
  4094                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4095                              <1> ;-------------------------------------------------------------------------------
  4096                              <1> NEC_TERM:
  4097                              <1> 
  4098                              <1> ;-----	LET THE OPERATION HAPPEN
  4099                              <1> 
  4100 00002039 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4101 0000203A E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4102 0000203F 9C                  <1> 	PUSHFd	; 05/12/2021
  4103 00002040 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4104 00002045 724B                <1> 	JC	short SET_END_POP
  4105 00002047 9D                  <1> 	POPFd	; 05/12/2021
  4106 00002048 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4107                              <1> 
  4108                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4109                              <1> 
  4110 0000204A FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4111 0000204B BE[0D700000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4112 00002050 AC                  <1> 	lodsb				; GET ST0
  4113 00002051 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4114 00002053 7433                <1> 	JZ	short SET_END
  4115 00002055 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4116 00002057 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4117                              <1> 
  4118                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4119                              <1> 
  4120 00002059 AC                  <1> 	lodsb				; GET ST1
  4121 0000205A D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4122 0000205C B404                <1> 	MOV	AH,RECORD_NOT_FND
  4123 0000205E 7222                <1> 	JC	short J19
  4124 00002060 C0E002              <1> 	SAL	AL,2
  4125 00002063 B410                <1> 	MOV	AH,BAD_CRC
  4126 00002065 721B                <1> 	JC	short J19
  4127 00002067 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4128 00002069 B408                <1> 	MOV	AH,BAD_DMA
  4129 0000206B 7215                <1> 	JC	short J19
  4130 0000206D C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4131 00002070 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4132 00002072 720E                <1> 	JC	short J19
  4133 00002074 D0E0                <1> 	SAL	AL,1
  4134 00002076 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4135 00002078 7208                <1> 	JC	short J19
  4136 0000207A D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4137 0000207C B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4138 0000207E 7202                <1> 	JC	short J19
  4139                              <1> 
  4140                              <1> ;----- 	NEC MUST HAVE FAILED
  4141                              <1> J18:
  4142 00002080 B420                <1> 	MOV	AH,BAD_NEC
  4143                              <1> J19:
  4144 00002082 0825[0C700000]      <1> 	OR	[DSKETTE_STATUS],AH
  4145                              <1> SET_END:
  4146 00002088 803D[0C700000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4147 0000208F F5                  <1> 	CMC
  4148 00002090 5E                  <1> 	POP	eSI
  4149 00002091 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4150                              <1> 
  4151                              <1> SET_END_POP:
  4152 00002092 9D                  <1> 	POPFd	; 05/12/2021
  4153 00002093 EBF3                <1> 	JMP	SHORT SET_END
  4154                              <1> 
  4155                              <1> ;-------------------------------------------------------------------------------
  4156                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4157                              <1> ;-------------------------------------------------------------------------------
  4158                              <1> DSTATE:
  4159 00002095 803D[0C700000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4160 0000209C 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4161 0000209E 808F[19700000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4162 000020A5 F687[19700000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4163 000020AC 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4164 000020AE 8A87[19700000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4165 000020B4 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4166 000020B6 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4167 000020B8 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4168                              <1> 
  4169                              <1> ;----- 	CHECK IF IT IS 1.44M
  4170                              <1> 
  4171 000020BA E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4172                              <1> 	;;20/02/2015
  4173                              <1> 	;;JC	short M_12		; CMOS BAD
  4174 000020BF 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4175 000020C1 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4176 000020C3 7410                <1> 	JE	short M_12		; YES
  4177                              <1> M_720:
  4178 000020C5 80A7[19700000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4179 000020CC 808F[19700000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4180 000020D3 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4181                              <1> M_12:	
  4182 000020D5 808F[19700000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4183                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4184                              <1> SETBAC:
  4185 000020DC C3                  <1> 	RETn
  4186                              <1> 
  4187                              <1> ;-------------------------------------------------------------------------------
  4188                              <1> ; RETRY	
  4189                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4190                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4191                              <1> ;
  4192                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4193                              <1> ;-------------------------------------------------------------------------------
  4194                              <1> RETRY:
  4195 000020DD 803D[0C700000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4196 000020E4 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4197 000020E6 803D[0C700000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4198 000020ED 743C                <1> 	JZ	short NO_RETRY
  4199 000020EF 8AA7[19700000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4200 000020F5 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4201 000020F8 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4202 000020FA 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4203 000020FD 8A2D[14700000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4204 00002103 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4205 00002106 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4206 00002109 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4207 0000210B 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4208                              <1> 
  4209                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4210                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4211                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4212                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4213                              <1> 
  4214 0000210D 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4215 00002110 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4216 00002112 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4217 00002115 80A7[19700000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4218                              <1> 					; RATE, DBL STEP OFF
  4219 0000211C 08A7[19700000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4220 00002122 C605[0C700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4221 00002129 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4222 0000212A C3                  <1> 	RETn				; RETRY RETURN
  4223                              <1> 
  4224                              <1> NO_RETRY:
  4225 0000212B F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4226 0000212C C3                  <1> 	RETn				; NO RETRY RETURN
  4227                              <1> 
  4228                              <1> ;-------------------------------------------------------------------------------
  4229                              <1> ; NUM_TRANS
  4230                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4231                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4232                              <1> ;
  4233                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4234                              <1> ;		SI-HI  = HEAD
  4235                              <1> ;		[BP]   = START SECTOR
  4236                              <1> ;
  4237                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4238                              <1> ;-------------------------------------------------------------------------------
  4239                              <1> NUM_TRANS:
  4240 0000212D 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4241 0000212F 803D[0C700000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4242                              <1> 	; 05/12/2021
  4243 00002136 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4244 00002138 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4245 0000213A E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4246 0000213F 8A1D[12700000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4247 00002145 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4248 00002148 3A2D[11700000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4249 0000214E 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4250 00002150 8A2D[10700000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4251 00002156 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4252 00002159 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4253 0000215B 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4254                              <1> DIF_HD:
  4255 0000215D 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4256                              <1> SAME_TRK:
  4257 0000215F 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4258 00002162 88D8                <1> 	MOV	AL,BL			; TO AL
  4259                              <1> NT_OUT:
  4260 00002164 C3                  <1> 	RETn
  4261                              <1> 
  4262                              <1> ;-------------------------------------------------------------------------------
  4263                              <1> ; SETUP_END
  4264                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4265                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4266                              <1> ;
  4267                              <1> ; ON EXIT:
  4268                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4269                              <1> ;-------------------------------------------------------------------------------
  4270                              <1> SETUP_END:
  4271 00002165 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4272                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4273 00002167 50                  <1> 	push	eax ; 05/12/2021
  4274 00002168 E8C6000000          <1> 	CALL	GET_PARM
  4275 0000216D 8825[0B700000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4276                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4277 00002173 58                  <1> 	pop	eax ; 05/12/2021
  4278 00002174 8A25[0C700000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4279 0000217A 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4280 0000217C 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4281 0000217E 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4282                              <1> NUN_ERR: 
  4283 00002180 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4284 00002183 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4285 00002184 C3                  <1> 	RETn
  4286                              <1> 
  4287                              <1> ;-------------------------------------------------------------------------------
  4288                              <1> ; SETUP_DBL
  4289                              <1> ;	CHECK DOUBLE STEP.
  4290                              <1> ;
  4291                              <1> ; ON ENTRY :	DI = DRIVE
  4292                              <1> ;
  4293                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4294                              <1> ;-------------------------------------------------------------------------------
  4295                              <1> SETUP_DBL:
  4296 00002185 8AA7[19700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4297 0000218B F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4298 0000218E 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4299                              <1> 
  4300                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4301                              <1> 
  4302 00002190 C605[09700000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4303 00002197 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4304 0000219C B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4305 0000219E E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4306 000021A3 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4307 000021A8 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4308                              <1> 
  4309                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4310                              <1> 
  4311 000021AA 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4312 000021AE F687[19700000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4313 000021B5 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4314 000021B7 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4315                              <1> 
  4316                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4317                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4318                              <1> ;	THEN SET DOUBLE STEP ON.
  4319                              <1> 
  4320                              <1> CNT_OK:
  4321 000021B9 C605[0B700000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4322                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4323                              <1> 	; 05/12/2021
  4324 000021C0 51                  <1> 	push	ecx
  4325 000021C1 C605[0C700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4326 000021C8 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4327 000021CB D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4328 000021CD C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4329                              <1> 	;PUSH	AX			; SAVE HEAD
  4330                              <1> 	; 05/12/2021
  4331 000021D0 50                  <1> 	push	eax
  4332 000021D1 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4333                              <1> 	;POP	AX			; RESTORE HEAD
  4334                              <1> 	; 05/12/2021
  4335 000021D6 58                  <1> 	pop	eax
  4336 000021D7 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4337 000021DA E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4338 000021DF 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4339 000021E0 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4340 000021E5 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4341                              <1> 	;POP	CX			; RESTORE COUNT
  4342                              <1> 	; 05/12/2021
  4343 000021E6 59                  <1> 	pop	ecx
  4344 000021E7 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4345 000021E9 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4346 000021EB 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4347 000021ED 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4348                              <1> 
  4349                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4350                              <1> 
  4351                              <1> SD_ERR:	
  4352 000021EF F9                  <1> 	STC				; SET CARRY FOR ERROR
  4353 000021F0 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4354                              <1> 
  4355                              <1> DO_CHK:
  4356 000021F1 8A0D[10700000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4357 000021F7 888F[1D700000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4358 000021FD D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4359 000021FF 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4360 00002201 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4361 00002203 808F[19700000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4362                              <1> NO_DBL:
  4363 0000220A F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4364 0000220B C3                  <1> 	RETn
  4365                              <1> 
  4366                              <1> ;-------------------------------------------------------------------------------
  4367                              <1> ; READ_ID
  4368                              <1> ;	READ ID FUNCTION.
  4369                              <1> ;
  4370                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4371                              <1> ;
  4372                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4373                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4374                              <1> ;-------------------------------------------------------------------------------
  4375                              <1> READ_ID:
  4376 0000220C B8[29220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4377 00002211 50                  <1> 	PUSH	eAX
  4378 00002212 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4379 00002214 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4380 00002219 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4381 0000221C 88C4                <1> 	MOV	AH,AL
  4382 0000221E E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4383 00002223 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4384 00002228 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4385                              <1> ER_3:
  4386 00002229 C3                  <1> 	RETn
  4387                              <1> 
  4388                              <1> ;-------------------------------------------------------------------------------
  4389                              <1> ; CMOS_TYPE
  4390                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4391                              <1> ;
  4392                              <1> ; ON ENTRY:	DI = DRIVE #
  4393                              <1> ;
  4394                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4395                              <1> ;-------------------------------------------------------------------------------
  4396                              <1> 
  4397                              <1> CMOS_TYPE: ; 11/12/2014
  4398 0000222A 8A87[7E6A0000]      <1> 	mov	al, [eDI+fd0_type]
  4399 00002230 20C0                <1> 	and 	al, al ; 18/12/2014
  4400 00002232 C3                  <1> 	retn
  4401                              <1> 
  4402                              <1> ;CMOS_TYPE:
  4403                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4404                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4405                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4406                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4407                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4408                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4409                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4410                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4411                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4412                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4413                              <1> ;TB:
  4414                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4415                              <1> ;BAD_CM:
  4416                              <1> ;	RETn				; CY, STATUS OF READ
  4417                              <1> 
  4418                              <1> ;-------------------------------------------------------------------------------
  4419                              <1> ; GET_PARM
  4420                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4421                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4422                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4423                              <1> ;	THE PARAMETER IN DL.
  4424                              <1> ;
  4425                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4426                              <1> ;
  4427                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4428                              <1> ;		AL,DH DESTROYED
  4429                              <1> ;-------------------------------------------------------------------------------
  4430                              <1> GET_PARM:
  4431                              <1> 	;PUSH	DS
  4432 00002233 56                  <1> 	PUSH	eSI
  4433                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4434                              <1>     	;MOV	DS,AX
  4435                              <1> 	;;mov	ax, cs
  4436                              <1> 	;;mov	ds, ax
  4437                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4438 00002234 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4439                              <1> 	;SUB	BH,BH			; BX = INDEX
  4440 00002236 81E3FF000000        <1> 	and	ebx, 0FFh
  4441                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4442                              <1> 	;
  4443                              <1> 	; 17/12/2014
  4444 0000223C 66A1[716A0000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4445 00002242 38E0                <1> 	cmp	al, ah
  4446 00002244 7425                <1> 	je	short gpndc
  4447 00002246 A2[726A0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4448 0000224B 53                  <1> 	push	ebx ; 08/02/2015
  4449 0000224C 88C3                <1> 	mov	bl, al 
  4450                              <1> 	; 11/12/2014
  4451 0000224E 8A83[7E6A0000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4452                              <1> 	; 18/12/2014
  4453 00002254 20C0                <1> 	and	al, al
  4454 00002256 7507                <1> 	jnz	short gpdtc
  4455 00002258 BB[5B6A0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4456 0000225D EB05                <1>         jmp     short gpdpu
  4457                              <1> gpdtc:	
  4458 0000225F E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4459                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4460                              <1> gpdpu:
  4461 00002264 891D[F8690000]      <1> 	mov	[DISK_POINTER], ebx
  4462 0000226A 5B                  <1> 	pop	ebx
  4463                              <1> gpndc:
  4464 0000226B 8B35[F8690000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4465 00002271 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4466 00002274 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4467 00002276 5E                  <1> 	POP	eSI
  4468                              <1> 	;POP	DS
  4469 00002277 C3                  <1> 	RETn
  4470                              <1> 
  4471                              <1> ;-------------------------------------------------------------------------------
  4472                              <1> ; MOTOR_ON
  4473                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4474                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4475                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4476                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4477                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4478                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4479                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4480                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4481                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4482                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4483                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4484                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4485                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4486                              <1> ;
  4487                              <1> ; ON ENTRY:	DI = DRIVE #
  4488                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4489                              <1> ;-------------------------------------------------------------------------------
  4490                              <1> MOTOR_ON:
  4491 00002278 53                  <1> 	PUSH	eBX			; SAVE REG.
  4492 00002279 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4493 0000227E 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4494 00002280 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4495 00002285 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4496                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4497                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4498                              <1> M_WAIT:
  4499 0000228A B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4500 0000228C E8A2FFFFFF          <1> 	CALL	GET_PARM
  4501                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4502                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4503                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4504 00002291 80FC08              <1> 	cmp	ah, 8
  4505                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4506 00002294 7702                <1> 	ja	short J13
  4507                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4508 00002296 B408                <1> 	mov	ah, 8
  4509                              <1> 
  4510                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4511                              <1> GP2:	
  4512                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4513                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4514 00002298 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4515 0000229D E80FF2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4516                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4517 000022A2 FECC                <1> 	dec	ah
  4518 000022A4 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4519                              <1> MOT_IS_ON:
  4520 000022A6 5B                  <1> 	POP	eBX			; RESTORE REG.
  4521 000022A7 C3                  <1> 	RETn
  4522                              <1> 
  4523                              <1> ;-------------------------------------------------------------------------------
  4524                              <1> ; TURN_ON
  4525                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4526                              <1> ;
  4527                              <1> ; ON ENTRY:	DI = DRIVE #
  4528                              <1> ;
  4529                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4530                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4531                              <1> ;		AX,BX,CX,DX DESTROYED
  4532                              <1> ;-------------------------------------------------------------------------------
  4533                              <1> TURN_ON:
  4534 000022A8 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4535 000022AA 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4536 000022AC C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4537 000022AF FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4538 000022B0 C605[0B700000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4539 000022B7 A0[0A700000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4540 000022BC 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4541 000022BE B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4542 000022C0 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4543                              <1> 
  4544                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4545                              <1> ;  BL = DRIVE SELECT DESIRED
  4546                              <1> ;  AH = MOTOR ON MASK DESIRED
  4547                              <1> 
  4548 000022C2 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4549 000022C4 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4550 000022C6 8425[0A700000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4551 000022CC 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4552                              <1> 
  4553                              <1> TURN_IT_ON:
  4554 000022CE 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4555 000022D0 8A3D[0A700000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4556 000022D6 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4557 000022D9 8025[0A700000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4558 000022E0 0825[0A700000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4559 000022E6 A0[0A700000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4560 000022EB 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4561 000022ED 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4562 000022F0 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4563 000022F1 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4564 000022F3 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4565 000022F6 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4566 000022F8 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4567 000022FC EE                  <1> 	OUT	DX,AL
  4568 000022FD 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4569                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4570 000022FF 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4571 00002301 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4572 00002302 C3                  <1> 	RETn
  4573                              <1> 
  4574                              <1> NO_MOT_WAIT:
  4575 00002303 FB                  <1> 	sti
  4576                              <1> no_mot_w1: ; 27/02/2015
  4577 00002304 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4578                              <1> 	;STI				; INTERRUPTS BACK ON
  4579 00002305 C3                  <1> 	RETn
  4580                              <1> 
  4581                              <1> ;-------------------------------------------------------------------------------
  4582                              <1> ; HD_WAIT
  4583                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4584                              <1> ;
  4585                              <1> ; ON ENTRY:	DI = DRIVE #
  4586                              <1> ;
  4587                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4588                              <1> ;-------------------------------------------------------------------------------
  4589                              <1> HD_WAIT:
  4590 00002306 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4591 00002308 E826FFFFFF          <1> 	CALL	GET_PARM
  4592 0000230D 08E4                <1> 	or	ah, ah	; 17/12/2014
  4593 0000230F 7519                <1> 	jnz	short DO_WAT
  4594 00002311 F605[0A700000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4595                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4596                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4597                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4598 00002318 741E                <1> 	jz	short HW_DONE
  4599 0000231A B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4600 0000231C 8A87[19700000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4601 00002322 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4602 00002324 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4603 00002326 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4604                              <1> ;GP3:
  4605 00002328 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4606                              <1> ;	JMP	SHORT DO_WAT
  4607                              <1> 
  4608                              <1> ;ISNT_WRITE:
  4609                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4610                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4611                              <1> 
  4612                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4613                              <1> DO_WAT:
  4614                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4615                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4616                              <1> J29:					; 	1 MILLISECOND LOOP
  4617                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4618 0000232A B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4619 0000232F E87DF1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4620                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4621 00002334 FECC                <1> 	dec	ah
  4622 00002336 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4623                              <1> HW_DONE:
  4624 00002338 C3                  <1> 	RETn
  4625                              <1> 
  4626                              <1> ;-------------------------------------------------------------------------------
  4627                              <1> ; NEC_OUTPUT
  4628                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4629                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4630                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4631                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4632                              <1> ; 
  4633                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4634                              <1> ;
  4635                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4636                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4637                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4638                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4639                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4640                              <1> ;		AX,CX,DX DESTROYED
  4641                              <1> ;-------------------------------------------------------------------------------
  4642                              <1> 
  4643                              <1> ; 09/12/2014 [Erdogan Tan] 
  4644                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4645                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4646                              <1> ;	This read only register facilitates the transfer of data between
  4647                              <1> ;	the system microprocessor and the controller.
  4648                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4649                              <1> ;	  with the system micrprocessor.
  4650                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4651                              <1> ;	  the transfer is to the controller.
  4652                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4653                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4654                              <1> ; Bit 3 - Reserved.
  4655                              <1> ; Bit 2 - Reserved.
  4656                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4657                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4658                              <1> 
  4659                              <1> ; Data Register (3F5h)
  4660                              <1> ; This read/write register passes data, commands and parameters, and provides
  4661                              <1> ; diskette status information.
  4662                              <1>   		
  4663                              <1> NEC_OUTPUT:
  4664                              <1> 	;PUSH	BX			; SAVE REG.
  4665 00002339 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4666                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4667                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4668                              <1> 	; 16/12/2014
  4669                              <1> 	; waiting for (max.) 0.5 seconds
  4670                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4671                              <1> 	;
  4672                              <1> 	; 17/12/2014
  4673                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4674                              <1> 	;
  4675                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4676                              <1> 	;		go on.
  4677                              <1> 	;INPUT:
  4678                              <1> 	;	AH=Mask for isolation bits.
  4679                              <1> 	;	AL=pattern to look for.
  4680                              <1> 	;	DX=Port to test for
  4681                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4682                              <1> 	;	     (normally 30 microseconds per period.)
  4683                              <1> 	;
  4684                              <1> 	;WFP_SHORT:  
  4685                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4686                              <1> 	;
  4687                              <1> 
  4688                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4689                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4690 0000233D B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4691                              <1> ;
  4692                              <1> ;WFPS_OUTER_LP:
  4693                              <1> ;	;
  4694                              <1> ;WFPS_CHECK_PORT:
  4695                              <1> J23:
  4696 00002342 EC                  <1> 	IN	AL,DX			; GET STATUS
  4697 00002343 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4698 00002345 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4699 00002347 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4700                              <1> WFPS_HI:
  4701 00002349 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4702 0000234B A810                <1> 	TEST	AL,010H			; transition on memory
  4703 0000234D 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4704                              <1> WFPS_LO:
  4705 0000234F E461                <1> 	IN	AL, PORT_B		; SYS1
  4706 00002351 A810                <1> 	TEST	AL,010H
  4707 00002353 74FA                <1> 	JZ	SHORT WFPS_LO
  4708                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4709 00002355 E2EB                <1> 	loop	J23	; 27/02/2015
  4710                              <1> ;	;
  4711                              <1> ;	dec	bl
  4712                              <1> ;	jnz	short WFPS_OUTER_LP
  4713                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4714                              <1> ;J23:
  4715                              <1> ;	IN	AL,DX			; GET STATUS
  4716                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4717                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4718                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4719                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4720                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4721                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4722                              <1>    
  4723                              <1> 	;;27/02/2015
  4724                              <1> 	;16/12/2014
  4725                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4726                              <1> 	;;jb	short J23
  4727                              <1> 
  4728                              <1> ;WFPS_TIMEOUT:
  4729                              <1> 
  4730                              <1> ;-----	FALL THRU TO ERROR RETURN
  4731                              <1> 
  4732 00002357 800D[0C700000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4733                              <1> 	;POP	BX			; RESTORE REG.
  4734 0000235E 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4735 0000235F F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4736 00002360 C3                  <1> 	RETn
  4737                              <1> 
  4738                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4739                              <1> 
  4740                              <1> J27:	
  4741 00002361 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4742 00002363 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4743 00002365 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4744                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4745                              <1> 	; 27/02/2015
  4746 00002366 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE FLAGS
  4747                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4748 00002367 29C9                <1> 	sub	ecx, ecx
  4749 00002369 B103                <1> 	mov	cl, 3 ; 05/12/2021
  4750 0000236B E841F1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4751 00002370 9D                  <1> 	POPFd	; 05/12/2021			; RESTORE FLAGS FOR EXIT
  4752                              <1> 	;POP	BX			; RESTORE REG
  4753 00002371 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4754                              <1> 
  4755                              <1> ;-------------------------------------------------------------------------------
  4756                              <1> ; SEEK
  4757                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4758                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4759                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4760                              <1> ;
  4761                              <1> ; ON ENTRY:	DI = DRIVE #
  4762                              <1> ;		CH = TRACK #
  4763                              <1> ;
  4764                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4765                              <1> ;		AX,BX,CX DX DESTROYED
  4766                              <1> ;-------------------------------------------------------------------------------
  4767                              <1> SEEK:
  4768 00002372 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4769 00002374 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4770 00002376 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4771 00002378 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4772 0000237A 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4773 0000237C 8405[09700000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4774 00002382 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4775                              <1> 
  4776 00002384 0805[09700000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4777 0000238A E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4778 0000238F 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4779                              <1> 
  4780                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4781                              <1> 
  4782 00002391 C605[0C700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4783 00002398 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4784 0000239D 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4785                              <1> 
  4786                              <1> AFT_RECAL:
  4787 0000239F C687[1D700000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4788 000023A6 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4789 000023A8 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4790                              <1> 
  4791                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4792                              <1> 
  4793 000023AA F687[19700000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4794 000023B1 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4795 000023B3 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4796                              <1> 
  4797 000023B5 3AAF[1D700000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4798 000023BB 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4799                              <1> 
  4800 000023BD BA[F0230000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4801 000023C2 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4802 000023C3 88AF[1D700000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4803 000023C9 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4804 000023CB E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4805 000023D0 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4806 000023D2 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4807 000023D4 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4808 000023D9 8AA7[1D700000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4809 000023DF E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4810 000023E4 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4811                              <1> 
  4812                              <1> ;-----	WAIT FOR HEAD SETTLE
  4813                              <1> 
  4814                              <1> DO_WAIT:
  4815 000023E9 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE STATUS
  4816 000023EA E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4817 000023EF 9D                  <1> 	POPFd	; 05/12/2021		; RESTORE STATUS
  4818                              <1> RB:
  4819                              <1> NEC_ERR:
  4820                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4821                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4822 000023F0 C3                  <1> 	RETn				; RETURN TO CALLER
  4823                              <1> 
  4824                              <1> ;-------------------------------------------------------------------------------
  4825                              <1> ; RECAL
  4826                              <1> ;	RECALIBRATE DRIVE
  4827                              <1> ;
  4828                              <1> ; ON ENTRY:	DI = DRIVE #
  4829                              <1> ;
  4830                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4831                              <1> ;-------------------------------------------------------------------------------
  4832                              <1> RECAL:
  4833                              <1> 	;PUSH	CX
  4834                              <1> 	; 05/12/2021
  4835 000023F1 51                  <1> 	push	ecx
  4836 000023F2 B8[0E240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4837 000023F7 50                  <1> 	PUSH	eAX
  4838 000023F8 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4839 000023FA E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4840 000023FF 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4841 00002401 88DC                <1> 	MOV	AH,BL
  4842 00002403 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4843 00002408 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4844 0000240D 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4845                              <1> RC_BACK:
  4846                              <1> 	;POP	CX
  4847                              <1> 	; 05/12/2021
  4848 0000240E 59                  <1> 	pop	ecx
  4849 0000240F C3                  <1> 	RETn
  4850                              <1> 
  4851                              <1> ;-------------------------------------------------------------------------------
  4852                              <1> ; CHK_STAT_2
  4853                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4854                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4855                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4856                              <1> ;
  4857                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4858                              <1> ;-------------------------------------------------------------------------------
  4859                              <1> CHK_STAT_2:
  4860 00002410 B8[38240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4861 00002415 50                  <1> 	PUSH	eAX
  4862 00002416 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4863 0000241B 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4864 0000241D B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4865 0000241F E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4866 00002424 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4867 00002429 720C                <1> 	JC	short J34
  4868 0000242B A0[0D700000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4869 00002430 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4870 00002432 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4871 00002434 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4872 00002436 F8                  <1> 	CLC				; GOOD RETURN
  4873                              <1> J34:
  4874 00002437 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4875                              <1> CS_BACK:
  4876 00002438 C3                  <1> 	RETn
  4877                              <1> J35:
  4878 00002439 800D[0C700000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4879 00002440 F9                  <1> 	STC				; ERROR RETURN CODE
  4880 00002441 EBF4                <1> 	JMP	SHORT J34
  4881                              <1> 
  4882                              <1> ;-------------------------------------------------------------------------------
  4883                              <1> ; WAIT_INT
  4884                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4885                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4886                              <1> ;	IF THE DRIVE IS NOT READY.
  4887                              <1> ;
  4888                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4889                              <1> ;-------------------------------------------------------------------------------
  4890                              <1> 
  4891                              <1> ; 17/12/2014
  4892                              <1> ; 2.5 seconds waiting !
  4893                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4894                              <1> ; amount of time to wait for completion interrupt from NEC.
  4895                              <1> 
  4896                              <1> 
  4897                              <1> WAIT_INT:
  4898 00002443 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4899 00002444 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4900                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4901                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4902                              <1> 
  4903                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4904                              <1> 	;
  4905                              <1> 	;WAIT_FOR_MEM:	
  4906                              <1> 	;	Waits for a bit at a specified memory location pointed
  4907                              <1> 	;	to by ES:[DI] to become set.
  4908                              <1> 	;INPUT:
  4909                              <1> 	;	AH=Mask to test with.
  4910                              <1> 	;	ES:[DI] = memory location to watch.
  4911                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4912                              <1> 	;	     (normally 30 microseconds per period.)
  4913                              <1> 
  4914                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4915                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4916                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4917                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4918                              <1> 	; 27/02/2015
  4919 00002445 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4920                              <1> WFMS_CHECK_MEM:
  4921 0000244A F605[09700000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4922 00002451 7516                <1>         jnz     short J37
  4923                              <1> WFMS_HI:
  4924 00002453 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4925 00002455 A810                <1> 	TEST	AL,010H			; transition on memory
  4926 00002457 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4927                              <1> WFMS_LO:
  4928 00002459 E461                <1> 	IN	AL,PORT_B		;SYS1
  4929 0000245B A810                <1> 	TEST	AL,010H
  4930 0000245D 74FA                <1> 	JZ	SHORT WFMS_LO
  4931 0000245F E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4932                              <1> ;WFMS_OUTER_LP:
  4933                              <1> ;;	or	bl, bl			; check outer counter
  4934                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4935                              <1> ;	dec	bl
  4936                              <1> ;	jz	short J36A	
  4937                              <1> ;	jmp	short WFMS_CHECK_MEM
  4938                              <1> 
  4939                              <1> 	;17/12/2014
  4940                              <1> 	;16/12/2014
  4941                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4942                              <1> ;J36:
  4943                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4944                              <1> ;	JNZ	short J37
  4945                              <1> 	;16/12/2014
  4946                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4947                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4948                              <1> 	;JNZ	short J36
  4949                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4950                              <1> ;	jb	short J36
  4951                              <1> 
  4952                              <1> ;WFMS_TIMEOUT:
  4953                              <1> ;J36A:
  4954 00002461 800D[0C700000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4955 00002468 F9                  <1> 	STC				; ERROR RETURN
  4956                              <1> J37:
  4957 00002469 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4958 0000246A 8025[09700000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4959 00002471 9D                  <1> 	POPF				; RECOVER CARRY
  4960 00002472 C3                  <1> 	RETn				; GOOD RETURN CODE
  4961                              <1> 
  4962                              <1> ;-------------------------------------------------------------------------------
  4963                              <1> ; RESULTS
  4964                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4965                              <1> ;	FOLLOWING AN INTERRUPT.
  4966                              <1> ;
  4967                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4968                              <1> ;		AX,BX,CX,DX DESTROYED
  4969                              <1> ;-------------------------------------------------------------------------------
  4970                              <1> RESULTS:
  4971 00002473 57                  <1> 	PUSH	eDI
  4972 00002474 BF[0D700000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4973 00002479 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4974 0000247B 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4975                              <1> 
  4976                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4977                              <1> 
  4978                              <1> _R10: 
  4979                              <1> 	; 16/12/2014
  4980                              <1> 	; wait for (max) 0.5 seconds
  4981                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4982                              <1> 	;XOR	CX,CX			; COUNTER
  4983                              <1> 
  4984                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4985                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4986                              <1> 	; 27/02/2015
  4987 0000247F B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4988                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4989                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4990                              <1> 
  4991                              <1> WFPSR_OUTER_LP:
  4992                              <1> 	;
  4993                              <1> WFPSR_CHECK_PORT:
  4994                              <1> J39:					; WAIT FOR MASTER
  4995 00002484 EC                  <1> 	IN	AL,DX			; GET STATUS
  4996 00002485 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4997 00002487 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4998 00002489 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  4999                              <1> WFPSR_HI:
  5000 0000248B E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  5001 0000248D A810                <1> 	TEST	AL,010H			; transition on memory
  5002 0000248F 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  5003                              <1> WFPSR_LO:
  5004 00002491 E461                <1> 	IN	AL, PORT_B		; SYS1
  5005 00002493 A810                <1> 	TEST	AL,010H
  5006 00002495 74FA                <1> 	JZ	SHORT WFPSR_LO
  5007 00002497 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  5008                              <1> 	;; 27/02/2015
  5009                              <1> 	;;dec	bh
  5010                              <1> 	;;jnz	short WFPSR_OUTER_LP
  5011                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  5012                              <1> 
  5013                              <1> 	;;mov	byte [wait_count], 0
  5014                              <1> ;J39:					; WAIT FOR MASTER
  5015                              <1> ;	IN	AL,DX			; GET STATUS
  5016                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5017                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5018                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  5019                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  5020                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  5021                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  5022                              <1> 	;
  5023                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  5024                              <1> 	;;jb	short J39	
  5025                              <1> 
  5026                              <1> ;WFPSR_TIMEOUT:
  5027 00002499 800D[0C700000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5028 000024A0 F9                  <1> 	STC				; SET ERROR RETURN
  5029 000024A1 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5030                              <1> 
  5031                              <1> ;-----	READ IN THE STATUS
  5032                              <1> 
  5033                              <1> J42:
  5034 000024A3 EB00                <1> 	JMP	$+2			; I/O DELAY
  5035 000024A5 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5036 000024A7 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5037                              <1> 	; 16/12/2014
  5038                              <1> 	NEWIODELAY
  2134 000024A8 E6EB                <2>  out 0EBh,al
  5039 000024AA 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5040 000024AC 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5041                              <1> 	; 16/12/2014
  5042                              <1> ;	push	cx
  5043                              <1> ;	mov	cx, 30
  5044                              <1> ;wdw2:
  5045                              <1> ;	NEWIODELAY
  5046                              <1> ;	loop	wdw2
  5047                              <1> ;	pop	cx
  5048                              <1> 
  5049 000024AD B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5050 000024B2 E8FAEFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5051 000024B7 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5052 000024B9 EC                  <1> 	IN	AL,DX			; GET STATUS
  5053                              <1> 	; 16/12/2014
  5054                              <1> 	NEWIODELAY
  2134 000024BA E6EB                <2>  out 0EBh,al
  5055                              <1> 	;
  5056 000024BC A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5057 000024BE 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5058                              <1> 
  5059 000024C0 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5060 000024C2 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5061 000024C4 800D[0C700000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5062 000024CB F9                  <1> 	STC				; SET ERROR FLAG
  5063                              <1> 
  5064                              <1> ;-----	RESULT OPERATION IS DONE
  5065                              <1> POPRES:
  5066 000024CC 5F                  <1> 	POP	eDI
  5067 000024CD C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5068                              <1> 
  5069                              <1> ;-------------------------------------------------------------------------------
  5070                              <1> ; READ_DSKCHNG
  5071                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5072                              <1> ;
  5073                              <1> ; ON ENTRY:	DI = DRIVE #
  5074                              <1> ;
  5075                              <1> ; ON EXIT:	DI = DRIVE #
  5076                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5077                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5078                              <1> ;		AX,CX,DX DESTROYED
  5079                              <1> ;-------------------------------------------------------------------------------
  5080                              <1> READ_DSKCHNG:
  5081 000024CE E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5082 000024D3 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5083 000024D7 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5084 000024D8 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5085 000024DA C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5086                              <1> 
  5087                              <1> ;-------------------------------------------------------------------------------
  5088                              <1> ; DRIVE_DET
  5089                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5090                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5091                              <1> ; ON ENTRY:	DI = DRIVE #
  5092                              <1> ;-------------------------------------------------------------------------------
  5093                              <1> DRIVE_DET:
  5094 000024DB E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5095 000024E0 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5096 000024E5 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5097 000024E7 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5098 000024E9 E884FEFFFF          <1> 	CALL	SEEK
  5099 000024EE 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5100 000024F0 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5101                              <1> SK_GIN:
  5102 000024F2 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5103                              <1> 	;PUSH	CX			; SAVE TRACK
  5104                              <1> 	; 05/12/2021
  5105 000024F4 51                  <1> 	push	ecx
  5106 000024F5 E878FEFFFF          <1> 	CALL	SEEK
  5107 000024FA 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5108 000024FC B8[37250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5109 00002501 50                  <1> 	PUSH	eAX
  5110 00002502 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5111 00002504 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5112 00002509 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5113 0000250C 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5114 0000250E E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5115 00002513 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5116 00002518 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5117                              <1> 	;POP	CX			; RESTORE TRACK
  5118                              <1> 	; 05/12/2021
  5119 00002519 59                  <1> 	pop	ecx
  5120 0000251A F605[0D700000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5121 00002521 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5122 00002523 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5123 00002525 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5124                              <1> 
  5125                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5126                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5127                              <1> 
  5128 00002527 808F[19700000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5129 0000252E C3                  <1> 	RETn				; ALL INFORMATION SET
  5130                              <1> IS_80:
  5131 0000252F 808F[19700000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5132                              <1> DD_BAC:
  5133 00002536 C3                  <1> 	RETn
  5134                              <1> POP_BAC:
  5135                              <1> 	;POP	CX			; THROW AWAY
  5136                              <1> 	; 05/12/2021
  5137 00002537 59                  <1> 	pop	ecx
  5138 00002538 C3                  <1> 	RETn
  5139                              <1> 
  5140                              <1> fdc_int:  
  5141                              <1> 	  ; 30/07/2015	
  5142                              <1> 	  ; 16/02/2015
  5143                              <1> ;int_0Eh: ; 11/12/2014
  5144                              <1> 
  5145                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5146                              <1> ; DISK_INT
  5147                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5148                              <1> ;
  5149                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5150                              <1> ;-------------------------------------------------------------------------------
  5151                              <1> DISK_INT_1:
  5152                              <1> 
  5153                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5154                              <1> 	; 05/12/2021
  5155 00002539 50                  <1> 	push	eax
  5156 0000253A 1E                  <1> 	push	ds
  5157 0000253B 66B81000            <1> 	mov	ax, KDATA
  5158 0000253F 8ED8                <1> 	mov 	ds, ax
  5159 00002541 800D[09700000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5160 00002548 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5161 0000254A E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5162 0000254C 1F                  <1> 	pop	ds
  5163                              <1> 	;POP	AX			; RECOVER REGISTER
  5164                              <1> 	; 05/12/2021
  5165 0000254D 58                  <1> 	pop	eax
  5166 0000254E CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5167                              <1> 
  5168                              <1> ;-------------------------------------------------------------------------------
  5169                              <1> ; DSKETTE_SETUP
  5170                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5171                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5172                              <1> ;-------------------------------------------------------------------------------
  5173                              <1> DSKETTE_SETUP:
  5174                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5175                              <1> 	;PUSH	BX
  5176                              <1> 	;PUSH	CX
  5177 0000254F 52                  <1> 	PUSH	eDX
  5178                              <1> 	;PUSH	DI
  5179                              <1> 	;;PUSH	DS
  5180                              <1> 	; 14/12/2014
  5181                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5182                              <1> 	;mov	[DISK_POINTER+2], cs
  5183                              <1> 	;
  5184                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5185 00002550 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5186 00002552 66C705[19700000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5186 0000255A 00                  <1>
  5187 0000255B 8025[14700000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5188 00002562 800D[14700000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5189 00002569 C605[09700000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5190 00002570 C605[0B700000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5191 00002577 C605[0A700000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5192 0000257E C605[0C700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5193                              <1> 	;
  5194                              <1> 	; 28/02/2015
  5195                              <1> 	;mov	word [cfd], 100h 
  5196 00002585 E89DF2FFFF          <1> 	call	DSK_RESET
  5197 0000258A 5A                  <1> 	pop	edx
  5198 0000258B C3                  <1> 	retn
  5199                              <1> 
  5200                              <1> ;SUP0:
  5201                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5202                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5203                              <1> ;	; 02/01/2015
  5204                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5205                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5206                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5207                              <1> ;       cmp     byte [fd1_type], 0	
  5208                              <1> ;	jna	short sup1
  5209                              <1> ;	or	di, di
  5210                              <1> ;	jnz	short sup1
  5211                              <1> ;	inc	di
  5212                              <1> ;       jmp     short SUP0
  5213                              <1> ;sup1:
  5214                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5215                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5216                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5217                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5218                              <1> ;	;POP	DI
  5219                              <1> ;	POP	eDX
  5220                              <1> ;	;POP	CX
  5221                              <1> ;	;POP	BX
  5222                              <1> ;	;POP	AX
  5223                              <1> ;	RETn
  5224                              <1> 
  5225                              <1> ;//////////////////////////////////////////////////////
  5226                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5227                              <1> ;
  5228                              <1> 
  5229                              <1> int13h: ; 21/02/2015
  5230 0000258C 9C                  <1> 	pushfd
  5231 0000258D 0E                  <1> 	push 	cs
  5232 0000258E E858000000          <1> 	call 	DISK_IO
  5233 00002593 C3                  <1> 	retn
  5234                              <1> 
  5235                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5236                              <1> ;/////////////////////////////////////////////////////////////////////
  5237                              <1> 
  5238                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5239                              <1> ; 23/02/2015
  5240                              <1> ; 21/02/2015 (unix386.s)
  5241                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5242                              <1> ;
  5243                              <1> ; Original Source Code:
  5244                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5245                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5246                              <1> ;
  5247                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5248                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5249                              <1> ;
  5250                              <1> 
  5251                              <1> ;The wait for controller to be not busy is 10 seconds.
  5252                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5253                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5254                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5255                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5256                              <1> 
  5257                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5258                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5259                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5260                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5261                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5262                              <1> 
  5263                              <1> ;The wait for Data request on read and write longs is
  5264                              <1> ;2000 us. (?)
  5265                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5266                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5267                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5268                              <1> 
  5269                              <1> ; Port 61h (PORT_B)
  5270                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5271                              <1> 
  5272                              <1> ; 23/12/2014
  5273                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5274                              <1> 
  5275                              <1> ;--- INT 13H -------------------------------------------------------------------
  5276                              <1> ;									       :
  5277                              <1> ; FIXED DISK I/O INTERFACE						       :
  5278                              <1> ;									       :
  5279                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5280                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5281                              <1> ;									       :
  5282                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5283                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5284                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5285                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5286                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5287                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5288                              <1> ;									       :
  5289                              <1> ;------------------------------------------------------------------------------:
  5290                              <1> ;									       :
  5291                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5292                              <1> ;									       :
  5293                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5294                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5295                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5296                              <1> ;			  DL > 80H - DISK				       :
  5297                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5298                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5299                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5300                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5301                              <1> ;	(AH)= 06H  UNUSED						       :
  5302                              <1> ;	(AH)= 07H  UNUSED						       :
  5303                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5304                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5305                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5306                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5307                              <1> ;	(AH)= 0AH  READ LONG						       :
  5308                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5309                              <1> ;	(AH)= 0CH  SEEK 						       :
  5310                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5311                              <1> ;	(AH)= 0EH  UNUSED						       :
  5312                              <1> ;	(AH)= 0FH  UNUSED						       :
  5313                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5314                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5315                              <1> ;	(AH)= 12H  UNUSED						       :
  5316                              <1> ;	(AH)= 13H  UNUSED						       :
  5317                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5318                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5319                              <1> ;									       :
  5320                              <1> ;-------------------------------------------------------------------------------
  5321                              <1> ;									       :
  5322                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5323                              <1> ;									       :
  5324                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5325                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5326                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5327                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5328                              <1> ;									       :
  5329                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5330                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5331                              <1> ;				 (10 BITS TOTAL)			       :
  5332                              <1> ;									       :
  5333                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5334                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5335                              <1> ;									       :
  5336                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5337                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5338                              <1> ;									       :
  5339                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5340                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5341                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5342                              <1> ;			       80H FOR A BAD SECTOR			       :
  5343                              <1> ;			   N = SECTOR NUMBER				       :
  5344                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5345                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5346                              <1> ;									       :
  5347                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5348                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5349                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5350                              <1> ;									       :
  5351                              <1> ;-------------------------------------------------------------------------------
  5352                              <1> 
  5353                              <1> ;-------------------------------------------------------------------------------
  5354                              <1> ; OUTPUT								       :
  5355                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5356                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5357                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5358                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5359                              <1> ;									       :
  5360                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5361                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5362                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5363                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5364                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5365                              <1> ;		REWRITTEN.						       :
  5366                              <1> ;									       :
  5367                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5368                              <1> ;	   INPUT:							       :
  5369                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5370                              <1> ;	   OUTPUT:							       :
  5371                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5372                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5373                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5374                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5375                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5376                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5377                              <1> ;									       :
  5378                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5379                              <1> ;									       :
  5380                              <1> ;	AH = 0 - NOT PRESENT						       :
  5381                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5382                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5383                              <1> ;	     3 - FIXED DISK						       :
  5384                              <1> ;									       :
  5385                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5386                              <1> ;									       :
  5387                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5388                              <1> ;	INFORMATION.							       :
  5389                              <1> ;									       :
  5390                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5391                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5392                              <1> ;									       :
  5393                              <1> ;-------------------------------------------------------------------------------
  5394                              <1> 
  5395                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5396                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5397                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5398                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5399                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5400                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5401                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5402                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5403                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5404                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5405                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5406                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5407                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5408                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5409                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5410                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5411                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5412                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5413                              <1> 
  5414                              <1> ;--------------------------------------------------------
  5415                              <1> ;							:
  5416                              <1> ; FIXED DISK PARAMETER TABLE				:
  5417                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5418                              <1> ;							:
  5419                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5420                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5421                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5422                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5423                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5424                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5425                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5426                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5427                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5428                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5429                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5430                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5431                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5432                              <1> ;							:
  5433                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5434                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5435                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5436                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5437                              <1> ;							:
  5438                              <1> ;--------------------------------------------------------
  5439                              <1> 
  5440                              <1> ;--------------------------------------------------------
  5441                              <1> ;							:
  5442                              <1> ; HARDWARE SPECIFIC VALUES				:
  5443                              <1> ;							:
  5444                              <1> ;  -  CONTROLLER I/O PORT				:
  5445                              <1> ;							:
  5446                              <1> ;     > WHEN READ FROM: 				:
  5447                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5448                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5449                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5450                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5451                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5452                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5453                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5454                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5455                              <1> ;							:
  5456                              <1> ;     > WHEN WRITTEN TO:				:
  5457                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5458                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5459                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5460                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5461                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5462                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5463                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5464                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5465                              <1> ;							:
  5466                              <1> ;--------------------------------------------------------
  5467                              <1> 
  5468                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5469                              <1> ;HF1_PORT	equ	0170h	
  5470                              <1> ;HF_REG_PORT	EQU	03F6H
  5471                              <1> ;HF1_REG_PORT	equ	0376h
  5472                              <1> 
  5473                              <1> HDC1_BASEPORT	equ	1F0h
  5474                              <1> HDC2_BASEPORT	equ	170h		
  5475                              <1> 
  5476                              <1> align 2
  5477                              <1> 
  5478                              <1> ;-----		STATUS REGISTER
  5479                              <1> 
  5480                              <1> ST_ERROR	EQU	00000001B	;
  5481                              <1> ST_INDEX	EQU	00000010B	;
  5482                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5483                              <1> ST_DRQ		EQU	00001000B	;
  5484                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5485                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5486                              <1> ST_READY	EQU	01000000B	;
  5487                              <1> ST_BUSY 	EQU	10000000B	;
  5488                              <1> 
  5489                              <1> ;-----		ERROR REGISTER
  5490                              <1> 
  5491                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5492                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5493                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5494                              <1> ;		EQU	00001000B	; NOT USED
  5495                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5496                              <1> ;		EQU	00100000B	; NOT USED
  5497                              <1> ERR_DATA_ECC	EQU	01000000B
  5498                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5499                              <1> 
  5500                              <1> 
  5501                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5502                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5503                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5504                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5505                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5506                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5507                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5508                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5509                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5510                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5511                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5512                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5513                              <1> 
  5514                              <1> ;MAX_FILE	EQU	2
  5515                              <1> ;S_MAX_FILE	EQU	2
  5516                              <1> MAX_FILE	equ	4		; 22/12/2014
  5517                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5518                              <1> 
  5519                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5520                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5521                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5522                              <1> 
  5523                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5524                              <1> 
  5525                              <1> ;-----		COMMAND BLOCK REFERENCE
  5526                              <1> 
  5527                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5528                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5529                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5530                              <1> ; 19/12/2014
  5531                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5532                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5533                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5534                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5535                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5536                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5537                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5538                              <1> 
  5539                              <1> align 2
  5540                              <1> 
  5541                              <1> ;----------------------------------------------------------------
  5542                              <1> ; FIXED DISK I/O SETUP						:
  5543                              <1> ;								:
  5544                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5545                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5546                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5547                              <1> ;								:
  5548                              <1> ;----------------------------------------------------------------
  5549                              <1> 
  5550                              <1> DISK_SETUP:
  5551                              <1> 	;CLI
  5552                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5553                              <1> 	;xor	ax,ax
  5554                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5555                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5556                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5557                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5558                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5559                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5560                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5561                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5562                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5563                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5564                              <1> 	;;MOV	[HDISK_INT+2],CS
  5565                              <1> 	;mov	[HDISK_INT1+2],CS
  5566                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5567                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5568                              <1> 	;mov	[HDISK_INT2+2],CS
  5569                              <1> 	;
  5570                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5571                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5572                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5573                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5574                              <1> 	;push	cs
  5575                              <1> 	;pop	ds
  5576                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5577                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5578 00002594 C705[24700000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5578 0000259C 0900                <1>
  5579                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5580                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5581 0000259E C705[28700000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5581 000025A6 0900                <1>
  5582                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5583                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5584 000025A8 C705[2C700000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5584 000025B0 0900                <1>
  5585                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5586                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5587 000025B2 C705[30700000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5587 000025BA 0900                <1>
  5588                              <1> 	;
  5589                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5590                              <1> 	;;;AND	AL,0BFH
  5591                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5592                              <1> 	;;;JMP	$+2
  5593                              <1> 	;;IODELAY
  5594                              <1> 	;;OUT	INTB01,AL
  5595                              <1> 	;;IODELAY
  5596                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5597                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5598                              <1> 	;;;JMP	$+2
  5599                              <1> 	;;IODELAY
  5600                              <1> 	;;OUT	INTA01,AL
  5601                              <1> 	;
  5602                              <1> 	;STI
  5603                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5604                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5605                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5606                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5607                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5608                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5609                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5610                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5611                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5612                              <1> 	;mov	si, hd0_type
  5613 000025BC BE[806A0000]        <1> 	mov	esi, hd0_type
  5614                              <1> 	;mov	cx, 4
  5615 000025C1 B904000000          <1> 	mov	ecx, 4
  5616                              <1> hde_l:
  5617 000025C6 AC                  <1> 	lodsb
  5618 000025C7 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5619 000025C9 7206                <1> 	jb	short _L4
  5620 000025CB FE05[20700000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5621                              <1> _L4: ; 26/02/2015
  5622 000025D1 E2F3                <1> 	loop	hde_l	
  5623                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5624                              <1> ;L4:
  5625                              <1> 	; 
  5626                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5627                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5628                              <1> 	;;mov 	cl, 3
  5629                              <1> 	;;
  5630                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5631                              <1> ;;hdc_dl:
  5632                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5633                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5634                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5635                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5636                              <1> 	;;jnc	short hdc_reset0
  5637                              <1> 	;;loop	hdc_dl
  5638                              <1> 	;;; 27/12/2014
  5639                              <1> 	;;stc
  5640                              <1> 	;;retn
  5641                              <1> 	;
  5642                              <1> ;;hdc_reset0:
  5643                              <1> 	; 18/01/2015
  5644 000025D3 8A0D[20700000]      <1> 	mov	cl, [HF_NUM]
  5645 000025D9 20C9                <1> 	and	cl, cl
  5646 000025DB 740D                <1> 	jz	short POD_DONE
  5647                              <1> 	;
  5648 000025DD B27F                <1> 	mov	dl, 7Fh
  5649                              <1> hdc_reset1:
  5650 000025DF FEC2                <1> 	inc	dl
  5651                              <1> 	;; 31/12/2015
  5652                              <1> 	;;push	dx
  5653                              <1> 	;;push	cx
  5654                              <1> 	;;push	ds
  5655                              <1> 	;;sub	ax, ax
  5656                              <1> 	;;mov	ds, ax
  5657                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5658                              <1> 	;;pop	ds
  5659                              <1> 	;;MOV	BX,AX
  5660                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5661                              <1> 	;;MOV	CX,AX
  5662                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5663                              <1> 	;;
  5664                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5665                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5666                              <1> 	;;pop	cx
  5667                              <1> 	;;pop	dx
  5668                              <1> 	;;
  5669                              <1> 	; 18/01/2015
  5670 000025E1 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5671                              <1> 	;int	13h
  5672 000025E3 E8A4FFFFFF          <1> 	call	int13h
  5673 000025E8 E2F5                <1> 	loop	hdc_reset1
  5674                              <1> POD_DONE:
  5675 000025EA C3                  <1> 	RETn
  5676                              <1> 
  5677                              <1> ;;-----	POD_ERROR
  5678                              <1> 
  5679                              <1> ;;CTL_ERRX:
  5680                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5681                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5682                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5683                              <1> ;	;JMP	short POD_DONE
  5684                              <1> 
  5685                              <1> ;;HD_RESET_1:
  5686                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5687                              <1> ;;	;PUSH	CX
  5688                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5689                              <1> ;;	INT	13H
  5690                              <1> ;;	JC	short RES_2
  5691                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5692                              <1> ;;	INT	13H
  5693                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5694                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5695                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5696                              <1> ;;					; (30 seconds)		
  5697                              <1> ;;	;cmc
  5698                              <1> ;;	;JNC	short RES_1
  5699                              <1> ;;	jb	short RES_1
  5700                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5701                              <1> ;;	;TEST	DL,1
  5702                              <1> ;;	;JNZ	RES_E1
  5703                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5704                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5705                              <1> ;;	;JMP	SHORT RES_E1
  5706                              <1> ;;RES_ER: ; 22/12/2014
  5707                              <1> ;;RES_OK:
  5708                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5709                              <1> ;;	;POP	BX
  5710                              <1> ;;	RETn
  5711                              <1> ;;
  5712                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5713                              <1> ;;	INT	13H
  5714                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5715                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5716                              <1> ;;	INT	13H
  5717                              <1> ;;	JC	short RES_ER
  5718                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5719                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5720                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5721                              <1> ;;	INT	13H
  5722                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5723                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5724                              <1> ;;	JE	short RES_OK
  5725                              <1> ;;	CMP	AH,DATA_CORRECTED
  5726                              <1> ;;	JE	short RES_OK
  5727                              <1> ;;	CMP	AH,BAD_ECC
  5728                              <1> ;;	JE	short RES_OK
  5729                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5730                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5731                              <1> ;;					; (60 seconds)		
  5732                              <1> ;;	cmc
  5733                              <1> ;;	JC	short RES_ER		; FAILED
  5734                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5735                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5736                              <1> ;;	AND	AL,3FH
  5737                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5738                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5739                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5740                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5741                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5742                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5743                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5744                              <1> ;;	;TEST	DL,1
  5745                              <1> ;;	;JNZ	short RES_E1
  5746                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5747                              <1> ;;;RES_E1:
  5748                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5749                              <1> ;;;RES_OK:
  5750                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5751                              <1> ;;	;POP	BX
  5752                              <1> ;;	;RETn
  5753                              <1> ;
  5754                              <1> ;;SET_FAIL:
  5755                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5756                              <1> ;	;CALL	CMOS_READ
  5757                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5758                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5759                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5760                              <1> ;	;RETn
  5761                              <1> ;
  5762                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5763                              <1> ;	;POP	AX			; SAVE RETURN
  5764                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5765                              <1> ;	;POP	BX
  5766                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5767                              <1> ;	;PUSH	CX
  5768                              <1> ;	;PUSH	AX
  5769                              <1> ;	;push	ds
  5770                              <1> ;	;xor	ax, ax
  5771                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5772                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5773                              <1> ;	;				; BX = START TIME
  5774                              <1> ;	;				; CX = END TIME
  5775                              <1> ;	;pop	ds
  5776                              <1> ;	;CMP	BX,CX
  5777                              <1> ;	;JB	short TCHK1		; START < END
  5778                              <1> ;	;CMP	BX,AX
  5779                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5780                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5781                              <1> ;;TCHK1: CMP	AX,BX
  5782                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5783                              <1> ;;TCHK2: CMP	AX,CX
  5784                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5785                              <1> ;;					; OR CURRENT < END < START
  5786                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5787                              <1> ;;	RETn
  5788                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5789                              <1> ;;	RETn
  5790                              <1> ;;
  5791                              <1> ;;int_13h:
  5792                              <1> 
  5793                              <1> ;----------------------------------------
  5794                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5795                              <1> ;----------------------------------------
  5796                              <1> 
  5797                              <1> DISK_IO:
  5798 000025EB 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5799                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5800                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5801                              <1> 	;;call	int40h
  5802                              <1> 	;jb	DISKETTE_IO_1
  5803                              <1> 	; 05/12/2021
  5804 000025EE 7305                <1> 	jnb	short A1
  5805 000025F0 E960F1FFFF          <1> 	jmp	DISKETTE_IO_1
  5806                              <1> ;RET_2:
  5807                              <1> 	;RETf	2			; BACK TO CALLER
  5808                              <1> ;	retf	4
  5809                              <1> A1:
  5810 000025F5 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5811                              <1> 	;; 04/01/2015
  5812                              <1> 	;;OR	AH,AH
  5813                              <1> 	;;JNZ	short A2
  5814                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5815                              <1> 	;;SUB	AH,AH
  5816 000025F6 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5817 000025F9 772E                <1> 	JA	short RET_2
  5818                              <1> 	; 18/01/2015
  5819 000025FB 08E4                <1> 	or	ah,ah
  5820 000025FD 742D                <1> 	jz	short A4
  5821 000025FF 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5822 00002602 7504                <1> 	jne	short A2
  5823 00002604 28E4                <1> 	sub	ah,ah	; Reset
  5824 00002606 EB24                <1> 	jmp	short A4
  5825                              <1> A2:
  5826 00002608 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5827                              <1> 	;JNZ	short A3
  5828                              <1>         ;JMP    GET_PARM_N
  5829                              <1> 	;je	GET_PARM_N
  5830                              <1> 	; 05/12/2021
  5831 0000260B 7505                <1> 	jne	short A3
  5832 0000260D E90D030000          <1> 	jmp	GET_PARM_N
  5833                              <1> A3:	
  5834 00002612 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5835                              <1> 	;JNZ	short A4
  5836                              <1>         ;JMP    READ_DASD_TYPE
  5837                              <1> 	;je	READ_DASD_TYPE
  5838                              <1> 	; 05/12/2021
  5839 00002615 7505                <1> 	jne	short A3_A4
  5840 00002617 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5841                              <1> A3_A4:
  5842                              <1> 	; 02/02/2015
  5843 0000261C 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5844                              <1> 	; 12/01/2015
  5845 0000261F F5                  <1> 	cmc
  5846 00002620 730A                <1> 	jnc	short A4
  5847                              <1> 	; 30/01/2015
  5848                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5849 00002622 C605[1F700000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5850                              <1> 	;jmp	short RET_2
  5851                              <1> RET_2:
  5852 00002629 CA0400              <1> 	retf	4
  5853                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5854 0000262C C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5855 00002630 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5856 00002631 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5857 00002632 52                  <1> 	PUSH	eDX
  5858 00002633 1E                  <1> 	PUSH	DS
  5859 00002634 06                  <1> 	PUSH	ES
  5860 00002635 56                  <1> 	PUSH	eSI
  5861 00002636 57                  <1> 	PUSH	eDI
  5862                              <1> 	;;04/01/2015
  5863                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5864                              <1> 	;;JNZ	short A5
  5865                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5866                              <1> ;;A5:	
  5867                              <1> 	;push	cs
  5868                              <1> 	;pop	ds
  5869                              <1> 	; 21/02/2015
  5870                              <1> 	;push	ax
  5871                              <1> 	; 05/12/2021
  5872 00002637 50                  <1> 	push	eax
  5873 00002638 66B81000            <1> 	mov	ax, KDATA
  5874 0000263C 8ED8                <1> 	mov	ds, ax
  5875 0000263E 8EC0                <1> 	mov	es, ax	
  5876                              <1> 	;pop	ax
  5877                              <1> 	; 05/12/2021
  5878 00002640 58                  <1> 	pop	eax
  5879 00002641 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5880                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5881 00002646 8A25[1F700000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5882 0000264C 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5883 0000264F F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5884 00002650 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5885 00002651 5E                  <1> 	POP	eSI
  5886 00002652 07                  <1>         POP     ES
  5887 00002653 1F                  <1>         POP     DS
  5888 00002654 5A                  <1> 	POP	eDX
  5889 00002655 59                  <1> 	POP	eCX
  5890 00002656 5B                  <1> 	POP	eBX
  5891 00002657 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5892                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5893 00002658 CA0400              <1> 	retf	4
  5894                              <1> ; 21/02/2015
  5895                              <1> ;       dw --> dd
  5896                              <1> M1:					; FUNCTION TRANSFER TABLE
  5897 0000265B [14280000]          <1> 	dd	DISK_RESET		; 000H
  5898 0000265F [89280000]          <1> 	dd	RETURN_STATUS		; 001H
  5899 00002663 [96280000]          <1> 	dd	DISK_READ		; 002H
  5900 00002667 [9F280000]          <1> 	dd	DISK_WRITE		; 003H
  5901 0000266B [A8280000]          <1> 	dd	DISK_VERF		; 004H
  5902 0000266F [C0280000]          <1> 	dd	FMT_TRK 		; 005H
  5903 00002673 [0A280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5904 00002677 [0A280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5905 0000267B [0A280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5906 0000267F [81290000]          <1> 	dd	INIT_DRV		; 009H
  5907 00002683 [E0290000]          <1> 	dd	RD_LONG 		; 00AH
  5908 00002687 [E9290000]          <1> 	dd	WR_LONG 		; 00BH
  5909 0000268B [F2290000]          <1> 	dd	DISK_SEEK		; 00CH
  5910 0000268F [14280000]          <1> 	dd	DISK_RESET		; 00DH
  5911 00002693 [0A280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5912 00002697 [0A280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5913 0000269B [1A2A0000]          <1> 	dd	TST_RDY 		; 010H
  5914 0000269F [3E2A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5915 000026A3 [0A280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5916 000026A7 [0A280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5917 000026AB [742A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5918                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5919 000026AF [0A280000]          <1> 	dd	BAD_COMMAND		; 015h
  5920 000026B3 [0A280000]          <1> 	dd	BAD_COMMAND		; 016h
  5921 000026B7 [0A280000]          <1> 	dd	BAD_COMMAND		; 017h
  5922 000026BB [0A280000]          <1> 	dd	BAD_COMMAND		; 018h
  5923 000026BF [0A280000]          <1> 	dd	BAD_COMMAND		; 019h
  5924 000026C3 [0A280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5925 000026C7 [96280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5926 000026CB [9F280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5927                              <1> M1L     EQU    $-M1
  5928                              <1> 
  5929                              <1> DISK_IO_CONT:
  5930                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5931 000026CF 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5932                              <1> 	;;JNZ	short SU0
  5933                              <1>         ;;JMP	RETURN_STATUS
  5934                              <1> 	;je	RETURN_STATUS
  5935                              <1> 	; 05/12/2021
  5936 000026D2 7505                <1> 	jne	short SU0
  5937 000026D4 E9B0010000          <1> 	jmp	RETURN_STATUS
  5938                              <1> SU0:
  5939 000026D9 C605[1F700000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5940                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5941                              <1> 	;mov	si, bx ;; 14/02/2015
  5942 000026E0 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5943 000026E2 8A1D[20700000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5944                              <1> 	;; 04/01/2015
  5945                              <1> 	;;PUSH	AX
  5946 000026E8 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5947                              <1> 					; (get drive number as 0 to 3)
  5948 000026EB 38D3                <1> 	CMP	BL,DL
  5949                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5950                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5951                              <1> 	; 05/12/2021
  5952 000026ED 7705                <1> 	ja	short su0_su1
  5953 000026EF E916010000          <1> 	jmp	BAD_COMMAND
  5954                              <1> su0_su1:
  5955                              <1>         ;;03/01/2015
  5956 000026F4 29DB                <1> 	sub	ebx, ebx
  5957 000026F6 88D3                <1> 	mov	bl, dl
  5958                              <1> 	;sub	bh, bh
  5959 000026F8 883D[34700000]      <1> 	mov	[LBAMode], bh 	; 0
  5960                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5961                              <1> 	;test	byte [ebx+hd0_type], 1
  5962                              <1> 	;jz	short su1		; no
  5963                              <1> 	;inc	byte [LBAMode]
  5964                              <1> ;su1:
  5965                              <1> 	; 21/02/2015 (32 bit modification)
  5966                              <1> 	; 04/01/2015
  5967                              <1> 	;push	ax ; ***
  5968                              <1> 	; 05/12/2021
  5969 000026FE 50                  <1> 	push	eax ; ***
  5970                              <1> 	;PUSH	ES ; **
  5971                              <1> 	;PUSH	DX ; *
  5972                              <1> 	; 05/12/2021
  5973 000026FF 52                  <1> 	push	edx ; *
  5974                              <1> 	;push	ax
  5975 00002700 50                  <1> 	push	eax
  5976 00002701 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5977                              <1> 	; 02/02/2015
  5978                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5979 00002706 668B4310            <1> 	mov	ax, [ebx+16]
  5980 0000270A 66A3[746A0000]      <1> 	mov	[HF_PORT], ax
  5981                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5982 00002710 668B5312            <1> 	mov	dx, [ebx+18]
  5983 00002714 668915[766A0000]    <1> 	mov	[HF_REG_PORT], dx
  5984                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5985 0000271B 8A4314              <1> 	mov	al, [ebx+20]
  5986                              <1> 	; 23/02/2015
  5987 0000271E A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5988 00002720 7406                <1> 	jz 	short su1
  5989 00002722 FE05[34700000]      <1> 	inc	byte [LBAMode] ; 1 
  5990                              <1> su1: 	 
  5991 00002728 C0E804              <1> 	shr 	al, 4
  5992 0000272B 2401                <1> 	and	al, 1			
  5993 0000272D A2[786A0000]        <1> 	mov	[hf_m_s], al 
  5994                              <1> 	;
  5995                              <1> 	; 03/01/2015
  5996                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  5997 00002732 8A4308              <1> 	mov	al, [ebx+8]
  5998                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  5999 00002735 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  6000                              <1> 					; Control Byte:  (= 08h, here)
  6001                              <1> 					; bit 0 - 0
  6002                              <1> 					; bit 1 - nIEN (1 = disable irq)
  6003                              <1> 					; bit 2 - SRST (software RESET)
  6004                              <1> 					; bit 3 - use extra heads (8 to 15)
  6005                              <1> 					;         -always set to 1-	
  6006                              <1> 					; (bits 3 to 7 are reserved
  6007                              <1> 					;          for ATA devices)
  6008 00002736 8A25[21700000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6009 0000273C 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  6010 0000273F 08C4                <1> 	OR	AH,AL
  6011 00002741 8825[21700000]      <1> 	MOV	[CONTROL_BYTE],AH	
  6012                              <1> 	; 04/01/2015
  6013                              <1> 	;pop	ax
  6014                              <1> 	; 05/12/2021
  6015 00002747 58                  <1> 	pop	eax
  6016                              <1> 	;pop	dx ; * ;; 14/02/2015
  6017                              <1> 	; 05/12/2021
  6018 00002748 5A                  <1> 	pop	edx ; *
  6019 00002749 20E4                <1> 	and	ah, ah	; Reset function ?
  6020 0000274B 7506                <1> 	jnz	short su2
  6021                              <1> 	;;pop	dx ; * ;; 14/02/2015
  6022                              <1> 	;pop	es ; **
  6023                              <1> 	;pop	ax ; ***
  6024                              <1> 	; 05/12/2021
  6025 0000274D 58                  <1> 	pop	eax ; ***	
  6026                              <1> 	;;pop	bx
  6027 0000274E E9C1000000          <1>         jmp     DISK_RESET
  6028                              <1> su2:
  6029 00002753 803D[34700000]00    <1> 	cmp	byte [LBAMode], 0
  6030 0000275A 765E                <1> 	jna	short su3
  6031                              <1> 	;
  6032                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6033 0000275C 80FC1B              <1> 	cmp	ah, 1Bh
  6034 0000275F 720B                <1> 	jb	short lbarw1
  6035 00002761 80FC1C              <1> 	cmp	ah, 1Ch
  6036 00002764 7759                <1> 	ja 	short invldfnc
  6037                              <1> 	;;pop	dx ; * ; 14/02/2015
  6038                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6039 00002766 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6040                              <1> 	;; 14/02/2015
  6041 00002768 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6042                              <1> 	;;mov	dx, bx
  6043                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6044                              <1> 	;;mov	bx, di
  6045                              <1> 	;mov	si, di ; Buffer offset
  6046 0000276A EB2E                <1> 	jmp	short lbarw2
  6047                              <1> lbarw1:
  6048                              <1> 	; convert CHS to LBA
  6049                              <1> 	;
  6050                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6051                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6052                              <1> 	;	+ Sector - 1
  6053                              <1> 	;push	dx ; * ;; 14/02/2015
  6054                              <1> 	; 05/12/2021
  6055 0000276C 52                  <1> 	push	edx ; *
  6056                              <1> 	;xor	dh, dh
  6057 0000276D 31D2                <1> 	xor	edx, edx
  6058                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6059 0000276F 8A530E              <1> 	mov	dl, [ebx+14]
  6060                              <1> 	;xor	ah, ah
  6061 00002772 31C0                <1> 	xor	eax, eax
  6062                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6063 00002774 8A4302              <1> 	mov	al, [ebx+2]
  6064 00002777 FEC8                <1> 	dec	al
  6065                              <1> 	;inc	ax		; 0 =  256
  6066 00002779 40                  <1> 	inc	eax ; 05/12/2021
  6067 0000277A 66F7E2              <1> 	mul 	dx
  6068                              <1> 		; AX = # of Heads" * Sectors/Track
  6069 0000277D 6689CA              <1> 	mov	dx, cx
  6070                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6071 00002780 83E13F              <1> 	and	ecx, 3fh
  6072 00002783 86D6                <1> 	xchg	dl, dh
  6073 00002785 C0EE06              <1> 	shr	dh, 6
  6074                              <1> 		; DX = cylinder (0 to 1023)
  6075                              <1> 	;mul 	dx
  6076                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6077 00002788 F7E2                <1> 	mul	edx
  6078 0000278A FEC9                <1> 	dec	cl  ; sector - 1
  6079                              <1> 	;add	ax, cx
  6080                              <1> 	;adc	dx, 0
  6081                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6082 0000278C 01C8                <1> 	add	eax, ecx
  6083                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6084                              <1> 	; 05/12/2021
  6085 0000278E 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6086                              <1> 	;push	dx
  6087                              <1> 	;push	ax
  6088 0000278F 50                  <1> 	push	eax
  6089                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6090 00002790 8A430E              <1> 	mov	al, [ebx+14]
  6091 00002793 F6E5                <1> 	mul	ch
  6092                              <1> 		; AX = Head * Sectors/Track
  6093 00002795 6699                <1>         cwd
  6094                              <1> 	;pop	dx
  6095 00002797 5A                  <1> 	pop	edx
  6096                              <1> 	;add	ax, dx
  6097                              <1> 	;pop	dx
  6098                              <1> 	;adc	dx, 0 ; add carry bit
  6099 00002798 01D0                <1> 	add	eax, edx
  6100                              <1> lbarw2:
  6101 0000279A 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6102 0000279C 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6103 0000279E C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6104                              <1> 				; NOTE: Features register (1F1h, 171h)
  6105                              <1> 				; is not used for ATA device R/W functions. 
  6106                              <1> 				; It is old/obsolete 'write precompensation'
  6107                              <1> 				; register and error register
  6108                              <1> 				; for old ATA/IDE devices.
  6109                              <1> 	; 18/01/2014
  6110                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6111 000027A2 8A0D[786A0000]      <1> 	mov	cl, [hf_m_s]
  6112                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6113                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6114                              <1> 				; bit 6 = 1 = LBA mode
  6115                              <1> 				; bit 7 = 1
  6116 000027A8 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6117                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6118 000027AB 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6119 000027B0 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6120                              <1> 	;or	dh, ch
  6121 000027B3 09C8                <1> 	or	eax, ecx	
  6122                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6123                              <1> 				  ; (Sector Number Register)
  6124                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6125                              <1> 				  ; (Cylinder Low Register)
  6126                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6127                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6128                              <1> 				  ; (Cylinder High Register)
  6129                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6130                              <1> 				  ; (Drive/Head Register)
  6131                              <1> 	
  6132                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6133 000027B5 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6134                              <1> 	;14/02/2015
  6135                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6136 000027B8 EB37                <1> 	jmp	short su4
  6137                              <1> su3:
  6138                              <1> 	; 02/02/2015 
  6139                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6140 000027BA 80FC14              <1> 	cmp 	ah, 14h
  6141 000027BD 7603                <1> 	jna 	short chsfnc
  6142                              <1> invldfnc:
  6143                              <1>         ; 14/02/2015  
  6144                              <1> 	;pop	es ; **
  6145                              <1>         ;pop	ax ; ***
  6146                              <1>         ; 05/12/2021
  6147 000027BF 58                  <1> 	pop	eax ; ***
  6148                              <1> 	;jmp	short BAD_COMMAND_POP
  6149 000027C0 EB48                <1>         jmp     short BAD_COMMAND
  6150                              <1> chsfnc:	
  6151                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6152 000027C2 668B4305            <1> 	mov	ax, [ebx+5]
  6153 000027C6 66C1E802            <1> 	SHR	AX,2
  6154 000027CA 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6155                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6156                              <1> 	;;PUSH	DX
  6157                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6158                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6159                              <1> 	;;POP	DX ; * 
  6160                              <1> 	;;POP	ES ; **
  6161                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6162                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6163                              <1> 	;;OR	AH,AL
  6164                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6165                              <1> 	;
  6166 000027CD 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6167 000027CF 243F                <1> 	AND	AL,3FH
  6168 000027D1 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6169 000027D4 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6170 000027D7 88C8                <1> 	MOV	AL,CL
  6171 000027D9 C0E806              <1> 	SHR	AL,6
  6172 000027DC 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6173                              <1> 	;;05/01/2015
  6174                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6175 000027DF A0[786A0000]        <1> 	mov	al, [hf_m_s]
  6176 000027E4 C0E004              <1> 	SHL	AL,4
  6177 000027E7 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6178 000027EA 08F0                <1> 	OR	AL,DH
  6179                              <1> 	;OR	AL,80H or 20H
  6180 000027EC 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6181 000027EE 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6182                              <1> su4:
  6183                              <1> 	;POP	ES ; **
  6184                              <1>         ;; 14/02/2015
  6185                              <1>         ;;POP   AX
  6186                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6187                              <1>         ;;PUSH  AX
  6188                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6189                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6190                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6191                              <1> 	;pop	ax ; ***
  6192                              <1> 	; 05/12/2021
  6193 000027F1 58                  <1> 	pop	eax ; ***
  6194 000027F2 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6195 000027F5 29DB                <1>         sub	ebx, ebx
  6196 000027F7 88E3                <1> 	mov     bl, ah
  6197                              <1>         ;xor	bh, bh
  6198                              <1>         ;sal	bx, 1
  6199 000027F9 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6200                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6201                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6202                              <1>         ;;JNB   short BAD_COMMAND_POP
  6203                              <1>         ;cmp	bx, M1L
  6204 000027FD 83FB74              <1> 	cmp	ebx, M1L
  6205 00002800 7308                <1> 	jnb	short BAD_COMMAND
  6206                              <1>         ;xchg	bx, si
  6207 00002802 87DE                <1>         xchg	ebx, esi
  6208                              <1> 	;;;POP	AX			; RESTORE AX
  6209                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6210                              <1> 	
  6211                              <1> 	;;PUSH	CX
  6212                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6213                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6214                              <1> 	;SHR	CX,4
  6215                              <1> 	;MOV	AX,ES
  6216                              <1> 	;ADD	AX,CX
  6217                              <1> 	;MOV	ES,AX
  6218                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6219                              <1> 	;;POP	AX
  6220                              <1> 	;;POP	CX
  6221                              <1> 	;;JMP	word [CS:SI+M1]
  6222                              <1> 	;jmp	word [SI+M1]
  6223 00002804 FFA6[5B260000]      <1> 	jmp	dword [esi+M1]
  6224                              <1> ;;BAD_COMMAND_POP:
  6225                              <1> ;;	POP	AX
  6226                              <1> ;;	POP	BX
  6227                              <1> BAD_COMMAND:
  6228 0000280A C605[1F700000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6229 00002811 B000                <1> 	MOV	AL,0
  6230 00002813 C3                  <1> 	RETn
  6231                              <1> 
  6232                              <1> ;----------------------------------------
  6233                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6234                              <1> ;----------------------------------------
  6235                              <1> 
  6236                              <1> ; 18-1-2015 : one controller reset (not other one)
  6237                              <1> 
  6238                              <1> DISK_RESET:
  6239 00002814 FA                  <1> 	CLI
  6240 00002815 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6241                              <1> 	;JMP	$+2
  6242                              <1> 	IODELAY
  2129 00002817 EB00                <2>  jmp short $+2
  2130 00002819 EB00                <2>  jmp short $+2
  6243                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6244 0000281B 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6245 0000281D E6A1                <1> 	OUT	INTB01,AL
  6246 0000281F FB                  <1> 	STI				; START INTERRUPTS
  6247                              <1> 	; 14/02/2015
  6248                              <1> 	;mov	di, dx
  6249                              <1> 	; 05/12/2021
  6250 00002820 89D7                <1> 	mov	edi, edx	
  6251                              <1> 	; 04/01/2015
  6252                              <1> 	;xor	di,di
  6253                              <1> drst0:
  6254 00002822 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6255                              <1> 	;MOV	DX,HF_REG_PORT
  6256 00002824 668B15[766A0000]    <1> 	MOV	DX,[HF_REG_PORT]
  6257 0000282B EE                  <1> 	OUT	DX,AL			; RESET
  6258                              <1> ;	MOV	CX,10			; DELAY COUNT
  6259                              <1> ;DRD:	DEC	CX
  6260                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6261                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6262 0000282C B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6263 00002831 E87BECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6264                              <1>                                         ; 40 micro seconds)
  6265 00002836 A0[21700000]        <1> 	mov	al,[CONTROL_BYTE]
  6266 0000283B 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6267 0000283D EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6268 0000283E E807040000          <1> 	CALL	NOT_BUSY
  6269 00002843 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6270 00002845 668B15[746A0000]    <1> 	MOV	DX,[HF_PORT]
  6271 0000284C FEC2                <1> 	inc	dl  ; HF_PORT+1
  6272                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6273                              <1>         ;mov	cl, 10
  6274 0000284E B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6275                              <1> drst1:
  6276 00002853 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6277 00002854 3C01                <1> 	CMP	AL,1
  6278                              <1> 	; 04/01/2015
  6279 00002856 740A                <1> 	jz	short drst2
  6280                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6281                              <1>         	; Drive/Head Register - bit 4
  6282 00002858 E2F9                <1> 	loop	drst1
  6283                              <1> DRERR:	
  6284 0000285A C605[1F700000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6285 00002861 C3                  <1> 	RETn
  6286                              <1> drst2:
  6287                              <1> 	; 14/02/2015
  6288                              <1> 	;mov	dx, di
  6289                              <1> 	; 05/12/2021
  6290 00002862 89FA                <1> 	mov	edx, edi
  6291                              <1> ;drst3:
  6292                              <1> ;	; 05/01/2015
  6293                              <1> ;	shl 	di,1
  6294                              <1> ;	; 04/01/2015
  6295                              <1> ;	mov	ax,[di+hd_cports]
  6296                              <1> ;	cmp	ax,[HF_REG_PORT]
  6297                              <1> ;	je	short drst4
  6298                              <1> ;	mov	[HF_REG_PORT], ax
  6299                              <1> ;	; 03/01/2015
  6300                              <1> ;	mov	ax,[di+hd_ports]
  6301                              <1> ;       mov     [HF_PORT], ax
  6302                              <1> ;	; 05/01/2014
  6303                              <1> ;	shr	di,1
  6304                              <1> ;	; 04/01/2015
  6305                              <1> ;	jmp	short drst0	; reset other controller
  6306                              <1> ;drst4:
  6307                              <1> ;	; 05/01/2015
  6308                              <1> ;	shr	di,1
  6309                              <1> ;	mov	al,[di+hd_dregs]
  6310                              <1> ;	and	al,10h ; bit 4 only
  6311                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6312                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6313                              <1> 	;
  6314 00002864 A0[786A0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6315 00002869 A801                <1> 	test	al,1
  6316                              <1> ;	jnz	short drst6
  6317 0000286B 7516                <1>         jnz     short drst4
  6318 0000286D 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6319                              <1> ;drst5:
  6320                              <1> drst3:
  6321 00002871 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6322                              <1> 	;mov	dx,di
  6323 00002876 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6324                              <1> 	; 04/01/2014
  6325                              <1> ;	inc	di
  6326                              <1> ;	mov	dx,di
  6327                              <1> ;	cmp	dl,[HF_NUM]
  6328                              <1> ;	jb	short drst3
  6329                              <1> ;DRE:
  6330 0000287B C605[1F700000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6331 00002882 C3                  <1> 	RETn
  6332                              <1> ;drst6:
  6333                              <1> drst4:		; Drive/Head Register - bit 4
  6334 00002883 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6335                              <1>         ;jmp    short drst5
  6336 00002887 EBE8                <1>         jmp     short drst3
  6337                              <1> 
  6338                              <1> ;----------------------------------------
  6339                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6340                              <1> ;----------------------------------------
  6341                              <1> 
  6342                              <1> RETURN_STATUS:
  6343 00002889 A0[1F700000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6344 0000288E C605[1F700000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6345 00002895 C3                  <1> 	RETn
  6346                              <1> 
  6347                              <1> ;----------------------------------------
  6348                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6349                              <1> ;----------------------------------------
  6350                              <1> 
  6351                              <1> DISK_READ:
  6352 00002896 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6353 0000289A E92A020000          <1>         JMP     COMMANDI
  6354                              <1> 
  6355                              <1> ;----------------------------------------
  6356                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6357                              <1> ;----------------------------------------
  6358                              <1> 
  6359                              <1> DISK_WRITE:
  6360 0000289F C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6361 000028A3 E976020000          <1>         JMP     COMMANDO
  6362                              <1> 
  6363                              <1> ;----------------------------------------
  6364                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6365                              <1> ;----------------------------------------
  6366                              <1> 
  6367                              <1> DISK_VERF:
  6368 000028A8 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6369 000028AC E8E4020000          <1> 	CALL	COMMAND
  6370 000028B1 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6371 000028B3 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6372 000028B8 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6373 000028BA E8E3030000          <1> 	CALL	CHECK_STATUS
  6374                              <1> VERF_EXIT:
  6375 000028BF C3                  <1> 	RETn
  6376                              <1> 
  6377                              <1> ;----------------------------------------
  6378                              <1> ;	FORMATTING	     (AH = 05H) :
  6379                              <1> ;----------------------------------------
  6380                              <1> 
  6381                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6382 000028C0 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6383                              <1> 	;PUSH	ES
  6384                              <1> 	;PUSH	BX
  6385 000028C4 53                  <1> 	push	ebx
  6386 000028C5 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6387                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6388 000028CA 8A430E              <1> 	mov	al, [ebx+14]
  6389 000028CD 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6390 000028D0 5B                  <1> 	pop	ebx
  6391                              <1> 	;POP	BX
  6392                              <1> 	;POP	ES
  6393 000028D1 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6394                              <1> 
  6395                              <1> ;----------------------------------------
  6396                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6397                              <1> ;----------------------------------------
  6398                              <1> 
  6399                              <1> READ_DASD_TYPE:
  6400                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6401 000028D6 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6402                              <1> 	;PUSH	ES
  6403 000028D7 53                  <1> 	PUSH	eBX
  6404                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6405                              <1> 	;push	cs
  6406                              <1> 	;pop	ds
  6407 000028D8 66BB1000            <1>         mov	bx, KDATA
  6408 000028DC 8EDB                <1> 	mov	ds, bx
  6409                              <1> 	;mov	es, bx
  6410 000028DE C605[1F700000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6411 000028E5 8A1D[20700000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6412 000028EB 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6413 000028EE 38D3                <1> 	CMP	BL,DL
  6414 000028F0 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6415 000028F2 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6416                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6417 000028F7 8A4302              <1> 	mov	al, [ebx+2]
  6418                              <1> 	;MOV	CL,[ES:BX+14]
  6419 000028FA 8A4B0E              <1> 	mov	cl, [ebx+14]
  6420 000028FD F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6421                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6422 000028FF 668B0B              <1> 	mov	cx, [ebx]
  6423                              <1> 	;
  6424                              <1> 	; 02/01/2015 
  6425                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6426                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6427 00002902 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6428                              <1> 	;
  6429 00002904 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6430 00002907 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6431 0000290A 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6432                              <1> 	;SUB	AX,AX
  6433 0000290D 28C0                <1> 	sub	al, al
  6434 0000290F B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6435 00002911 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6436                              <1> 	;POP	ES
  6437 00002912 1F                  <1> 	POP	DS
  6438 00002913 F8                  <1> 	CLC				; CLEAR CARRY
  6439                              <1> 	;RETf	2
  6440 00002914 CA0400              <1> 	retf	4
  6441                              <1> RDT_NOT_PRESENT:
  6442                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6443                              <1> 	; 05/12/2021
  6444 00002917 29C0                <1> 	sub	eax, eax
  6445                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6446                              <1> 	;MOV	DX,AX
  6447 00002919 89C1                <1> 	mov	ecx, eax
  6448 0000291B 89C2                <1> 	mov	edx, eax
  6449 0000291D EBF2                <1> 	JMP	short RDT2
  6450                              <1> 
  6451                              <1> ;----------------------------------------
  6452                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6453                              <1> ;----------------------------------------
  6454                              <1> 
  6455                              <1> GET_PARM_N:
  6456                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6457 0000291F 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6458                              <1> 	;PUSH	ES
  6459 00002920 53                  <1> 	PUSH	eBX
  6460                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6461                              <1> 	;MOV	DS,AX
  6462                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6463                              <1> 	;JZ	short G0
  6464                              <1> 	;LES	BX,@HF1_TBL_VEC
  6465                              <1> 	;JMP	SHORT G1
  6466                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6467                              <1> ;G1:
  6468                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6469                              <1> 	; 22/12/2014
  6470                              <1> 	;push	cs
  6471                              <1> 	;pop	ds
  6472 00002921 66BB1000            <1> 	mov	bx, KDATA
  6473 00002925 8EDB                <1> 	mov	ds, bx
  6474                              <1> 	;mov	es, bx
  6475                              <1> 	;
  6476 00002927 80EA80              <1> 	SUB	DL,80H
  6477 0000292A 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6478 0000292D 7340                <1> 	JAE	short G4
  6479                              <1> 	;
  6480 0000292F 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6481                              <1> 	; 22/12/2014
  6482 00002931 88D3                <1> 	mov	bl, dl
  6483                              <1> 	;xor	bh, bh  
  6484 00002933 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6485                              <1> 	;add	bx, HF_TBL_VEC
  6486 00002936 81C3[24700000]      <1> 	add	ebx, HF_TBL_VEC
  6487                              <1> 	;mov	ax, [bx+2]
  6488                              <1> 	;mov	es, ax			; dpt segment
  6489                              <1> 	;mov	bx, [bx]		; dpt offset
  6490 0000293C 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6491                              <1> 
  6492 0000293E C605[1F700000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6493                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6494 00002945 668B03              <1> 	mov	ax, [ebx]
  6495                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6496 00002948 6648                <1> 	dec	ax			; max. cylinder number
  6497 0000294A 88C5                <1> 	MOV	CH,AL
  6498 0000294C 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6499 00002950 66D1E8              <1> 	SHR	AX,1
  6500 00002953 66D1E8              <1> 	SHR	AX,1
  6501                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6502 00002956 0A430E              <1> 	or	al, [ebx+14]
  6503 00002959 88C1                <1> 	MOV	CL,AL
  6504                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6505 0000295B 8A7302              <1> 	mov	dh, [ebx+2]
  6506 0000295E FECE                <1> 	DEC	DH			; 0-N RANGE
  6507 00002960 8A15[20700000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6508                              <1> 	;SUB	AX,AX
  6509                              <1> 	; 05/12/2021
  6510 00002966 29C0                <1> 	sub	eax, eax
  6511                              <1> 	; 27/12/2014 
  6512                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6513                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6514                              <1> 	;mov	di, bx			; HDPT offset
  6515 00002968 89DF                <1> 	mov	edi, ebx
  6516                              <1> G5:
  6517 0000296A 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6518                              <1> 	;POP	ES
  6519 0000296B 1F                  <1> 	POP	DS
  6520                              <1> 	;RETf	2
  6521 0000296C CA0400              <1> 	retf	4
  6522                              <1> G4:
  6523 0000296F C605[1F700000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6524                              <1> 	; 05/12/2021
  6525 00002976 29C0                <1> 	sub	eax, eax
  6526 00002978 B407                <1> 	MOV	AH,INIT_FAIL
  6527                              <1> 	;SUB	AL,AL
  6528                              <1> 	;SUB	DX,DX
  6529 0000297A 29D2                <1> 	sub	edx, edx
  6530                              <1> 	;SUB	CX,CX
  6531 0000297C 29C9                <1> 	sub	ecx, ecx
  6532 0000297E F9                  <1> 	STC				; SET ERROR FLAG
  6533 0000297F EBE9                <1> 	JMP	short G5
  6534                              <1> 
  6535                              <1> ;----------------------------------------
  6536                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6537                              <1> ;----------------------------------------
  6538                              <1> 	; 03/01/2015
  6539                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6540                              <1> 	; logical sector per logical track
  6541                              <1> 	; and logical heads - 1 would be set but
  6542                              <1> 	; it is seen as it will be good
  6543                              <1> 	; if physical parameters will be set here
  6544                              <1> 	; because, number of heads <= 16.
  6545                              <1> 	; (logical heads usually more than 16)
  6546                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6547                              <1> 	;	== INT 13h physical parameters
  6548                              <1> 
  6549                              <1> ;INIT_DRV:
  6550                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6551                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6552                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6553                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6554                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6555                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6556                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6557                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6558                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6559                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6560                              <1> ;	SUB	AX,AX
  6561                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6562                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6563                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6564                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6565                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6566                              <1> ;	CALL	CHECK_STATUS
  6567                              <1> ;INIT_EXIT:
  6568                              <1> ;	RETn
  6569                              <1> 
  6570                              <1> ; 04/01/2015
  6571                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6572                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6573                              <1> INIT_DRV:
  6574                              <1> 	;xor	ah,ah
  6575 00002981 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6576 00002983 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6577 00002985 3825[34700000]      <1>         cmp     [LBAMode], ah   ; 0
  6578 0000298B 7702                <1> 	ja	short idrv0
  6579 0000298D B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6580                              <1> idrv0:
  6581                              <1> 	; DL = drive number (0 based)
  6582 0000298F E8BB030000          <1> 	call	GET_VEC
  6583                              <1> 	;push	bx
  6584 00002994 53                  <1> 	push	ebx ; 21/02/2015
  6585                              <1> 	;add	bx,ax
  6586 00002995 01C3                <1> 	add	ebx,eax
  6587                              <1> 	;; 05/01/2015
  6588 00002997 8A25[786A0000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6589                              <1> 	;;and 	ah,1 
  6590 0000299D C0E404              <1> 	shl	ah,4
  6591 000029A0 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6592                              <1> 	;mov	al,[es:bx]
  6593 000029A3 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6594 000029A5 FEC8                <1> 	dec	al	 ; last head number 
  6595                              <1> 	;and	al,0Fh
  6596 000029A7 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6597                              <1> 	;
  6598 000029A9 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6599 000029AD 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6600                              <1> 	;pop	bx
  6601 000029B0 5B                  <1> 	pop	ebx
  6602 000029B1 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6603 000029B3 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6604 000029B5 803D[34700000]00    <1> 	cmp	byte [LBAMode],0
  6605 000029BC 7702                <1> 	ja	short idrv1
  6606 000029BE B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6607                              <1> idrv1:
  6608                              <1> 	;xor	ah,ah
  6609                              <1> 	;add	bx,ax
  6610 000029C0 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6611                              <1> 	;mov	al,[es:bx]
  6612                              <1> 			; sector number
  6613 000029C2 8A03                <1> 	mov	al,[ebx]
  6614 000029C4 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6615 000029C7 28C0                <1> 	sub	al,al
  6616 000029C9 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6617 000029CC E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6618 000029D1 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6619 000029D3 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6620 000029D8 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6621 000029DA E8C3020000          <1> 	call	CHECK_STATUS
  6622                              <1> INIT_EXIT:
  6623 000029DF C3                  <1> 	RETn
  6624                              <1> 
  6625                              <1> ;----------------------------------------
  6626                              <1> ;	READ LONG	     (AH = 0AH) :
  6627                              <1> ;----------------------------------------
  6628                              <1> 
  6629                              <1> RD_LONG:
  6630                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6631 000029E0 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6632 000029E4 E9E0000000          <1>         JMP     COMMANDI
  6633                              <1> 
  6634                              <1> ;----------------------------------------
  6635                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6636                              <1> ;----------------------------------------
  6637                              <1> 
  6638                              <1> WR_LONG:
  6639                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6640 000029E9 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6641 000029ED E92C010000          <1>         JMP     COMMANDO
  6642                              <1> 
  6643                              <1> ;----------------------------------------
  6644                              <1> ;	SEEK		     (AH = 0CH) :
  6645                              <1> ;----------------------------------------
  6646                              <1> 
  6647                              <1> DISK_SEEK:
  6648 000029F2 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6649 000029F6 E89A010000          <1> 	CALL	COMMAND
  6650 000029FB 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6651 000029FD E80C020000          <1> 	CALL	_WAIT
  6652 00002A02 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6653 00002A04 E899020000          <1> 	CALL	CHECK_STATUS
  6654 00002A09 803D[1F700000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6655 00002A10 7507                <1> 	JNE	short DS_EXIT
  6656 00002A12 C605[1F700000]00    <1>         MOV     byte [DISK_STATUS1],0
  6657                              <1> DS_EXIT:
  6658 00002A19 C3                  <1> 	RETn
  6659                              <1> 
  6660                              <1> ;----------------------------------------
  6661                              <1> ;	TEST DISK READY      (AH = 10H) :
  6662                              <1> ;----------------------------------------
  6663                              <1> 
  6664                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6665 00002A1A E82B020000          <1> 	CALL	NOT_BUSY
  6666 00002A1F 751C                <1> 	JNZ	short TR_EX
  6667 00002A21 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6668 00002A24 668B15[746A0000]    <1> 	MOV	DX,[HF_PORT]
  6669 00002A2B 80C206              <1> 	add	dl,6
  6670 00002A2E EE                  <1> 	OUT	DX,AL
  6671 00002A2F E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6672 00002A34 7507                <1> 	JNZ	short TR_EX
  6673 00002A36 C605[1F700000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6674                              <1> TR_EX:	
  6675 00002A3D C3                  <1> 	RETn
  6676                              <1> 
  6677                              <1> ;----------------------------------------
  6678                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6679                              <1> ;----------------------------------------
  6680                              <1> 
  6681                              <1> HDISK_RECAL:
  6682 00002A3E C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6683 00002A42 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6684 00002A47 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6685 00002A49 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6686 00002A4E 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6687 00002A50 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6688 00002A55 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6689                              <1> RECAL_X:
  6690 00002A57 E846020000          <1> 	CALL	CHECK_STATUS
  6691 00002A5C 803D[1F700000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6692 00002A63 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6693 00002A65 C605[1F700000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6694                              <1> RECAL_EXIT:
  6695 00002A6C 803D[1F700000]00    <1>         CMP     byte [DISK_STATUS1],0
  6696 00002A73 C3                  <1> 	RETn
  6697                              <1> 
  6698                              <1> ;----------------------------------------
  6699                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6700                              <1> ;----------------------------------------
  6701                              <1> 
  6702                              <1> CTLR_DIAGNOSTIC:
  6703 00002A74 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6704 00002A75 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6705                              <1> 	;AND	AL,0BFH
  6706 00002A77 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6707                              <1> 	;JMP	$+2
  6708                              <1> 	IODELAY
  2129 00002A79 EB00                <2>  jmp short $+2
  2130 00002A7B EB00                <2>  jmp short $+2
  6709 00002A7D E6A1                <1> 	OUT	INTB01,AL
  6710                              <1> 	IODELAY
  2129 00002A7F EB00                <2>  jmp short $+2
  2130 00002A81 EB00                <2>  jmp short $+2
  6711 00002A83 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6712 00002A85 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6713                              <1> 	;JMP	$+2
  6714                              <1> 	IODELAY
  2129 00002A87 EB00                <2>  jmp short $+2
  2130 00002A89 EB00                <2>  jmp short $+2
  6715 00002A8B E621                <1> 	OUT	INTA01,AL
  6716 00002A8D FB                  <1> 	STI
  6717 00002A8E E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6718 00002A93 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6719                              <1> 	;MOV	DX, HF_PORT+7
  6720 00002A95 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  6721 00002A9C 80C207              <1> 	add	dl, 7
  6722 00002A9F B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6723 00002AA1 EE                  <1> 	OUT	DX,AL
  6724 00002AA2 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6725 00002AA7 B480                <1> 	MOV	AH,TIME_OUT
  6726 00002AA9 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6727                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6728 00002AAB 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  6729 00002AB2 FEC2                <1> 	inc	dl
  6730 00002AB4 EC                  <1> 	IN	AL,DX
  6731 00002AB5 A2[16700000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6732 00002ABA B400                <1> 	MOV	AH,0
  6733 00002ABC 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6734 00002ABE 7402                <1> 	JE	SHORT CD_EXIT
  6735 00002AC0 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6736                              <1> CD_EXIT:
  6737 00002AC2 8825[1F700000]      <1> 	MOV	[DISK_STATUS1],AH
  6738 00002AC8 C3                  <1> 	RETn
  6739                              <1> 
  6740                              <1> ;----------------------------------------
  6741                              <1> ; COMMANDI				:
  6742                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6743                              <1> ;	NSECTOR RETURNS ZERO		:
  6744                              <1> ;----------------------------------------
  6745                              <1> COMMANDI:
  6746 00002AC9 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6747 00002ACE 724D                <1> 	JC	short CMD_ABORT
  6748                              <1> 	;MOV	DI,BX
  6749 00002AD0 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6750 00002AD2 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6751 00002AD7 7544                <1> 	JNZ	short CMD_ABORT
  6752                              <1> CMD_I1:
  6753 00002AD9 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6754 00002ADE 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6755                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6756 00002AE0 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6757                              <1> 	;MOV	DX,HF_PORT
  6758 00002AE5 668B15[746A0000]    <1> 	mov	dx,[HF_PORT]
  6759 00002AEC FA                  <1> 	CLI
  6760 00002AED FC                  <1> 	CLD
  6761 00002AEE F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6762 00002AF1 FB                  <1> 	STI
  6763 00002AF2 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6764 00002AF6 7419                <1> 	JZ	CMD_I3
  6765 00002AF8 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6766 00002AFD 721E                <1> 	JC	short TM_OUT
  6767                              <1> 	;MOV	DX,HF_PORT
  6768 00002AFF 668B15[746A0000]    <1> 	mov	dx,[HF_PORT]
  6769                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6770 00002B06 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6771 00002B0B EC                  <1> CMD_I2: IN	AL,DX
  6772                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6773 00002B0C 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6774 00002B0E 47                  <1> 	INC	eDI
  6775 00002B0F E2FA                <1> 	LOOP	CMD_I2
  6776 00002B11 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6777 00002B16 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6778 00002B18 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6779 00002B1B 75BC                <1> 	JNZ	SHORT CMD_I1
  6780                              <1> CMD_ABORT:
  6781 00002B1D C3                  <1> TM_OUT: RETn
  6782                              <1> 
  6783                              <1> ;----------------------------------------
  6784                              <1> ; COMMANDO				:
  6785                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6786                              <1> ;	NSECTOR RETURNS ZERO		:
  6787                              <1> ;----------------------------------------
  6788                              <1> COMMANDO:
  6789 00002B1E E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6790 00002B23 72F8                <1> 	JC	short CMD_ABORT
  6791 00002B25 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6792 00002B27 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6793 00002B2C 75EF                <1> 	JNZ	short CMD_ABORT
  6794 00002B2E E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6795 00002B33 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6796                              <1> CMD_O1: ;PUSH	DS
  6797                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6798                              <1> 	;POP	DS
  6799                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6800                              <1> 	;MOV	DX,HF_PORT
  6801                              <1> 	; 01/02/2015
  6802 00002B35 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  6803                              <1> 	;push	es
  6804                              <1> 	;pop	ds
  6805                              <1> 	;mov	cx, 256
  6806 00002B3C B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6807 00002B41 FA                  <1> 	CLI
  6808 00002B42 FC                  <1> 	CLD
  6809 00002B43 F3666F              <1> 	REP	OUTSW
  6810 00002B46 FB                  <1> 	STI
  6811                              <1> 	;POP	DS			; RESTORE DS
  6812 00002B47 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6813 00002B4B 7419                <1> 	JZ	short CMD_O3
  6814 00002B4D E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6815 00002B52 72C9                <1> 	JC	short TM_OUT
  6816                              <1> 	;MOV	DX,HF_PORT
  6817 00002B54 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  6818                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6819 00002B5B B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6820                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6821 00002B60 8A06                <1> 	mov	al, [esi]
  6822 00002B62 EE                  <1> 	OUT	DX,AL
  6823 00002B63 46                  <1> 	INC	eSI
  6824 00002B64 E2FA                <1> 	LOOP	CMD_O2
  6825                              <1> CMD_O3:
  6826 00002B66 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6827 00002B6B 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6828 00002B6D E830010000          <1> 	CALL	CHECK_STATUS
  6829 00002B72 75A9                <1> 	JNZ	short CMD_ABORT
  6830 00002B74 F605[15700000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6831 00002B7B 75B8                <1> 	JNZ	SHORT CMD_O1
  6832                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6833 00002B7D 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  6834                              <1> 	;add	dl, 2
  6835 00002B84 FEC2                <1> 	inc	dl
  6836 00002B86 FEC2                <1> 	inc	dl
  6837 00002B88 EC                  <1> 	IN	AL,DX			;
  6838 00002B89 A8FF                <1> 	TEST	AL,0FFH 		;
  6839 00002B8B 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6840 00002B8D C605[1F700000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6841                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6842                              <1> CMD_O4:
  6843 00002B94 C3                  <1> 	RETn
  6844                              <1> 
  6845                              <1> ;--------------------------------------------------------
  6846                              <1> ; COMMAND						:
  6847                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6848                              <1> ; OUTPUT						:
  6849                              <1> ;	BL = STATUS					:
  6850                              <1> ;	BH = ERROR REGISTER				:
  6851                              <1> ;--------------------------------------------------------
  6852                              <1> 
  6853                              <1> COMMAND:
  6854 00002B95 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6855                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6856                              <1> COMMAND1:
  6857                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6858 00002B96 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6859                              <1> 	;;POP	CX
  6860 00002B9B 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6861 00002B9D 803D[1F700000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6862                              <1> 	;JZ	short CMD_TIMEOUT
  6863                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6864                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6865 00002BA4 7507                <1> 	jne	short COMMAND4
  6866                              <1> CMD_TIMEOUT:
  6867 00002BA6 C605[1F700000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6868                              <1> COMMAND4:
  6869 00002BAD 5B                  <1> 	POP	eBX
  6870 00002BAE 803D[1F700000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6871 00002BB5 C3                  <1> 	RETn
  6872                              <1> COMMAND2:
  6873 00002BB6 5B                  <1> 	POP	eBX
  6874 00002BB7 57                  <1> 	PUSH	eDI
  6875 00002BB8 C605[17700000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6876 00002BBF FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6877 00002BC0 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6878                              <1> 	;AND	AL,0BFH
  6879 00002BC2 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6880                              <1> 	;JMP	$+2
  6881                              <1> 	IODELAY
  2129 00002BC4 EB00                <2>  jmp short $+2
  2130 00002BC6 EB00                <2>  jmp short $+2
  6882 00002BC8 E6A1                <1> 	OUT	INTB01,AL
  6883 00002BCA E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6884 00002BCC 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6885                              <1> 	;JMP	$+2
  6886                              <1> 	IODELAY
  2129 00002BCE EB00                <2>  jmp short $+2
  2130 00002BD0 EB00                <2>  jmp short $+2
  6887 00002BD2 E621                <1> 	OUT	INTA01,AL
  6888 00002BD4 FB                  <1> 	STI
  6889 00002BD5 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6890                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6891 00002BD7 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  6892 00002BDE FEC2                <1> 	inc	dl
  6893 00002BE0 F605[21700000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6894 00002BE7 7411                <1> 	JZ	short COMMAND3
  6895 00002BE9 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6896 00002BEC 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6897 00002BEE 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6898 00002BF0 7208                <1> 	JB	short COMMAND3
  6899 00002BF2 3C40                <1> 	CMP	AL,40H
  6900 00002BF4 7704                <1> 	JA	short COMMAND3
  6901 00002BF6 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6902                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6903                              <1> COMMAND3:
  6904 00002BFA 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6905 00002BFE EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6906                              <1> 	IODELAY
  2129 00002BFF EB00                <2>  jmp short $+2
  2130 00002C01 EB00                <2>  jmp short $+2
  6907 00002C03 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6908 00002C04 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6909 00002C06 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6910 00002C0A 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6911 00002C0C 5F                  <1> 	POP	eDI
  6912 00002C0D C3                  <1> 	RETn				; ZERO FLAG IS SET
  6913                              <1> 
  6914                              <1> ;CMD_TIMEOUT:
  6915                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6916                              <1> ;COMMAND4:
  6917                              <1> ;	POP	BX
  6918                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6919                              <1> ;	RETn
  6920                              <1> 
  6921                              <1> ;----------------------------------------
  6922                              <1> ;	WAIT FOR INTERRUPT		:
  6923                              <1> ;----------------------------------------
  6924                              <1> ;WAIT:
  6925                              <1> _WAIT:
  6926 00002C0E FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6927                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6928                              <1> 	;CLC
  6929                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6930                              <1> 	;INT	15H
  6931                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6932                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6933                              <1> 
  6934                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6935                              <1> 	;; 21/02/2015
  6936                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6937                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6938 00002C0F B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6939                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6940                              <1> ;-----	WAIT LOOP
  6941                              <1> 
  6942                              <1> WT1:	
  6943                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6944 00002C14 F605[17700000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6945                              <1> 	;LOOPZ	WT1
  6946 00002C1B 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6947                              <1> 	;DEC	BL
  6948                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6949                              <1> 
  6950                              <1> WT1_hi:
  6951 00002C1D E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6952 00002C1F A810                <1> 	test	al, 10h			; transition on memory
  6953 00002C21 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6954                              <1> WT1_lo:
  6955 00002C23 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6956 00002C25 A810                <1> 	test	al, 10h			
  6957 00002C27 74FA                <1> 	jz	short WT1_lo
  6958 00002C29 E2E9                <1> 	loop	WT1
  6959                              <1> 	;;or	bl, bl
  6960                              <1> 	;;jz	short WT2	
  6961                              <1> 	;;dec	bl
  6962                              <1> 	;;jmp	short WT1
  6963                              <1> 	;dec	bl
  6964                              <1> 	;jnz	short WT1	
  6965                              <1> 
  6966 00002C2B C605[1F700000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6967 00002C32 EB0E                <1> 	JMP	SHORT WT4
  6968 00002C34 C605[1F700000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6969 00002C3B C605[17700000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6970 00002C42 803D[1F700000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6971 00002C49 C3                  <1> 	RETn
  6972                              <1> 
  6973                              <1> ;----------------------------------------
  6974                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6975                              <1> ;----------------------------------------
  6976                              <1> NOT_BUSY:
  6977 00002C4A FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6978                              <1> 	;PUSH	eBX
  6979                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6980 00002C4B 668B15[746A0000]    <1> 	mov	DX, [HF_PORT]
  6981 00002C52 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6982                              <1> 	;MOV	BL,DELAY_1
  6983                              <1> 					; wait for 10 seconds
  6984                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6985                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6986                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6987 00002C55 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6988                              <1> 	;
  6989                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6990                              <1> NB1:	
  6991 00002C5A EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6992                              <1> 	;TEST	AL,ST_BUSY
  6993 00002C5B 2480                <1> 	and	al, ST_BUSY
  6994                              <1> 	;LOOPNZ	NB1
  6995 00002C5D 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  6996                              <1> 	;DEC	BL			
  6997                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  6998                              <1> 
  6999 00002C5F E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  7000 00002C61 A810                <1> 	TEST	AL,010H			; transition on memory
  7001 00002C63 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  7002 00002C65 E461                <1> NB1_lo: IN	AL,SYS1
  7003 00002C67 A810                <1> 	TEST	AL,010H
  7004 00002C69 74FA                <1> 	JZ	short NB1_lo
  7005 00002C6B E2ED                <1> 	LOOP	NB1
  7006                              <1> 	;dec	bl
  7007                              <1> 	;jnz	short NB1
  7008                              <1> 	;
  7009                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  7010                              <1> ;;	jb	short NB1
  7011                              <1> 	;
  7012                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  7013                              <1> 	;JMP	SHORT NB3
  7014 00002C6D B080                <1> 	mov	al, TIME_OUT
  7015                              <1> NB2:	
  7016                              <1> 	;MOV	byte [DISK_STATUS1],0
  7017                              <1> ;NB3:	
  7018                              <1> 	;POP	eBX
  7019 00002C6F A2[1F700000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  7020                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  7021 00002C74 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  7022 00002C76 C3                  <1> 	RETn
  7023                              <1> 
  7024                              <1> ;----------------------------------------
  7025                              <1> ;	WAIT FOR DATA REQUEST		:
  7026                              <1> ;----------------------------------------
  7027                              <1> WAIT_DRQ:
  7028                              <1> 	;MOV	CX,DELAY_3
  7029                              <1> 	;MOV	DX,HF_PORT+7
  7030 00002C77 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  7031 00002C7E 80C207              <1> 	add	dl, 7
  7032                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7033                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7034                              <1> 					; (but it is written as 2000
  7035                              <1> 					; micro seconds in ATORGS.ASM file
  7036                              <1> 					; of Award Bios - 1999, D1A0622)
  7037 00002C81 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7038 00002C86 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7039 00002C87 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7040 00002C89 7516                <1> 	JNZ	short WQ_OK
  7041                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7042                              <1> WQ_hi:	
  7043 00002C8B E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7044 00002C8D A810                <1> 	TEST	AL,010H			; transition on memory
  7045 00002C8F 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7046 00002C91 E461                <1> WQ_lo:  IN      AL,SYS1
  7047 00002C93 A810                <1> 	TEST	AL,010H
  7048 00002C95 74FA                <1> 	JZ	SHORT WQ_lo
  7049 00002C97 E2ED                <1> 	LOOP	WQ_1
  7050                              <1> 
  7051 00002C99 C605[1F700000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7052 00002CA0 F9                  <1> 	STC
  7053                              <1> WQ_OK:
  7054 00002CA1 C3                  <1> 	RETn
  7055                              <1> ;WQ_OK:	;CLC
  7056                              <1> ;	RETn
  7057                              <1> 
  7058                              <1> ;----------------------------------------
  7059                              <1> ;	CHECK FIXED DISK STATUS 	:
  7060                              <1> ;----------------------------------------
  7061                              <1> CHECK_STATUS:
  7062 00002CA2 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7063 00002CA7 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7064 00002CA9 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7065 00002CAB 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7066 00002CAD E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7067                              <1> CHECK_S1:
  7068 00002CB2 803D[1F700000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7069 00002CB9 C3                  <1> 	RETn
  7070                              <1> 
  7071                              <1> ;----------------------------------------
  7072                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7073                              <1> ;----------------------------------------
  7074                              <1> CHECK_ST:
  7075                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7076 00002CBA 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]
  7077 00002CC1 80C207              <1> 	add	dl, 7
  7078 00002CC4 EC                  <1> 	IN	AL,DX
  7079 00002CC5 A2[15700000]        <1> 	MOV	[HF_STATUS],AL
  7080 00002CCA B400                <1> 	MOV	AH,0
  7081 00002CCC A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7082 00002CCE 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7083 00002CD0 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7084 00002CD2 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7085 00002CD4 7514                <1> 	JNZ	short CKST_EXIT
  7086 00002CD6 B4AA                <1> 	MOV	AH,NOT_RDY
  7087 00002CD8 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7088 00002CDA 740E                <1> 	JZ	short CKST_EXIT
  7089 00002CDC B440                <1> 	MOV	AH,BAD_SEEK
  7090 00002CDE A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7091 00002CE0 7408                <1> 	JZ	short CKST_EXIT
  7092 00002CE2 B411                <1> 	MOV	AH,DATA_CORRECTED
  7093 00002CE4 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7094 00002CE6 7502                <1> 	JNZ	short CKST_EXIT
  7095 00002CE8 B400                <1> 	MOV	AH,0
  7096                              <1> CKST_EXIT:
  7097 00002CEA 8825[1F700000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7098 00002CF0 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7099 00002CF3 7403                <1> 	JZ	short CKST_EX1
  7100 00002CF5 80FC00              <1> 	CMP	AH,0
  7101                              <1> CKST_EX1:
  7102 00002CF8 C3                  <1> 	RETn
  7103                              <1> 
  7104                              <1> ;----------------------------------------
  7105                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7106                              <1> ;----------------------------------------
  7107                              <1> CHECK_ER:
  7108                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7109 00002CF9 668B15[746A0000]    <1> 	mov	dx, [HF_PORT]		;
  7110 00002D00 FEC2                <1> 	inc	dl
  7111 00002D02 EC                  <1> 	IN	AL,DX
  7112 00002D03 A2[16700000]        <1> 	MOV	[HF_ERROR],AL
  7113 00002D08 53                  <1> 	PUSH	eBX ; 21/02/2015
  7114 00002D09 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7115 00002D0E D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7116 00002D10 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7117 00002D12 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7118 00002D14 BB[686A0000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7119 00002D19 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7120                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7121                              <1> 	;mov	ah, [bx]
  7122 00002D1B 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7123 00002D1D 8825[1F700000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7124 00002D23 5B                  <1> 	POP	eBX
  7125 00002D24 80FC00              <1> 	CMP	AH,0
  7126 00002D27 C3                  <1> 	RETn
  7127                              <1> 
  7128                              <1> ;--------------------------------------------------------
  7129                              <1> ; CHECK_DMA						:
  7130                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7131                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7132                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7133                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7134                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7135                              <1> ;  -ERROR OTHERWISE					:
  7136                              <1> ;--------------------------------------------------------
  7137                              <1> CHECK_DMA:
  7138                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7139                              <1> 	; 05/12/2021
  7140 00002D28 50                  <1> 	push	eax
  7141 00002D29 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7142 00002D2D F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7143 00002D31 7404                <1> 	JZ	short CKD1
  7144 00002D33 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7145 00002D37 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7146 00002D3A 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7147 00002D3C 7207                <1> 	JB	short CKDERR		; TOO MANY
  7148 00002D3E 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7149 00002D40 7203                <1> 	JB	short CKDERR		; ERROR
  7150 00002D42 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7151                              <1> 	;POP	AX
  7152                              <1> 	; 05/12/2021
  7153 00002D43 58                  <1> 	pop	eax
  7154 00002D44 C3                  <1> 	RETn				; NORMAL RETURN
  7155 00002D45 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7156 00002D46 C605[1F700000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7157                              <1> 	;POP	AX
  7158                              <1> 	; 05/12/2021
  7159 00002D4D 58                  <1> 	pop	eax	
  7160 00002D4E C3                  <1> 	RETn
  7161                              <1> 
  7162                              <1> ;----------------------------------------
  7163                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7164                              <1> ;----------------------------------------
  7165                              <1> 					
  7166                              <1> ; INPUT -> DL = 0 based drive number
  7167                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7168                              <1> 
  7169                              <1> GET_VEC:
  7170                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7171                              <1> 	;MOV	ES,AX
  7172                              <1> 	;TEST	DL,1
  7173                              <1> 	;JZ	short GV_0
  7174                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7175                              <1> ;	JMP	SHORT GV_EXIT
  7176                              <1> ;GV_0:
  7177                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7178                              <1> ;
  7179                              <1> 	;xor	bh, bh
  7180 00002D4F 31DB                <1> 	xor	ebx, ebx
  7181 00002D51 88D3                <1> 	mov	bl, dl
  7182                              <1> 	;;02/01/2015
  7183                              <1> 	;;shl	bl, 1			; port address offset
  7184                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7185                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7186 00002D53 C0E302              <1> 	shl	bl, 2	;;
  7187                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7188 00002D56 81C3[24700000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7189                              <1> 	;push	word [bx+2]		; dpt segment
  7190                              <1> 	;pop	es
  7191                              <1> 	;mov	bx, [bx]		; dpt offset
  7192 00002D5C 8B1B                <1> 	mov	ebx, [ebx]		
  7193                              <1> ;GV_EXIT:
  7194 00002D5E C3                  <1> 	RETn
  7195                              <1> 
  7196                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7197                              <1> hdc1_int: ; 21/02/2015
  7198                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7199                              <1> ;								:
  7200                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7201                              <1> ;								:
  7202                              <1> ;----------------------------------------------------------------
  7203                              <1> 
  7204                              <1> ; 22/12/2014
  7205                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7206                              <1> ;	 '11/15/85'
  7207                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7208                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7209                              <1> 
  7210                              <1> ;int_76h:
  7211                              <1> HD_INT:
  7212                              <1> 	;push	ax
  7213                              <1> 	; 05/12/2021
  7214 00002D5F 50                  <1> 	push	eax
  7215 00002D60 1E                  <1> 	push	ds
  7216                              <1> 	;CALL	DDS
  7217                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7218 00002D61 66B81000            <1> 	mov	ax, KDATA
  7219 00002D65 8ED8                <1> 	mov 	ds, ax
  7220                              <1> 	;
  7221                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7222                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7223 00002D67 C605[17700000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7224                              <1> 	;
  7225                              <1> 	;push	dx
  7226                              <1> 	; 05/12/2021
  7227 00002D6E 52                  <1> 	push	edx
  7228 00002D6F 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7229                              <1> 					; Clear Controller
  7230                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7231 00002D73 EC                  <1> 	in	al, dx			;
  7232                              <1> 	;pop	dx
  7233                              <1> 	; 05/12/2021
  7234 00002D74 5A                  <1> 	pop	edx
  7235                              <1> 	NEWIODELAY
  2134 00002D75 E6EB                <2>  out 0EBh,al
  7236                              <1> 	;
  7237 00002D77 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7238 00002D79 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7239                              <1> 	;JMP	$+2			; WAIT
  7240                              <1> 	NEWIODELAY
  2134 00002D7B E6EB                <2>  out 0EBh,al
  7241 00002D7D E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7242 00002D7F 1F                  <1> 	pop	ds
  7243                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7244                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7245                              <1> 	;INT	15H			;  INTERRUPT
  7246                              <1> irq15_iret: ; 25/02/2015
  7247                              <1> 	;pop	ax
  7248                              <1> 	; 05/12/2021
  7249 00002D80 58                  <1> 	pop	eax
  7250 00002D81 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7251                              <1> 
  7252                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7253                              <1> hdc2_int: ; 21/02/2015
  7254                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7255                              <1> ;								:
  7256                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7257                              <1> ;								:
  7258                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7259                              <1> 
  7260                              <1> ;int_77h:
  7261                              <1> HD1_INT:
  7262                              <1> 	;push	ax
  7263                              <1> 	; 05/12/2021
  7264 00002D82 50                  <1> 	push	eax
  7265                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7266                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7267 00002D83 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7268 00002D85 E6A0                <1> 	out	0A0h, al
  7269 00002D87 EB00                <1>         jmp short $+2
  7270 00002D89 EB00                <1> 	jmp short $+2
  7271 00002D8B E4A0                <1> 	in	al, 0A0h
  7272 00002D8D 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7273 00002D8F 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7274                              <1> 	;
  7275 00002D91 1E                  <1> 	push	ds
  7276                              <1> 	;CALL	DDS
  7277                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7278 00002D92 66B81000            <1> 	mov	ax, KDATA
  7279 00002D96 8ED8                <1> 	mov 	ds, ax
  7280                              <1> 	;
  7281                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7282                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7283 00002D98 800D[17700000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7284                              <1> 	;
  7285                              <1> 	;push	dx
  7286                              <1> 	; 05/12/2021
  7287 00002D9F 52                  <1> 	push	edx
  7288 00002DA0 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7289                              <1> 					; Clear Controller (Award BIOS 1999)
  7290 00002DA4 EBCD                <1> 	jmp	short Clear_IRQ1415
  7291                              <1> 
  7292                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7293                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7294                              <1> 
  7295                              <1> ;////////////////////////////////////////////////////////////////////
  7296                              <1> ;; END OF DISK I/O SYTEM ///
  2069                                  %include 'memory.s'  ; 09/03/2015
  2070                              <1> ; Retro UNIX 386 v2 - memory.s - 26/01/2020
  2071                              <1> ; Last Modification: 31/12/2021 (Retro UNIX 386 v1.2)
  2072                              <1> ; ----------------------------------------------------------------------------
  2073                              <1> ;
  2074                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2075                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC
  2076                              <1> ; 18/10/2015 (!not completed!)
  2077                              <1> ;
  2078                              <1> ; Source code for NASM - Netwide Assembler (2.11)
  2079                              <1> 
  2080                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2081                              <1> 
  2082                              <1> ;;04/11/2014 (unix386.s)	
  2083                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2084                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2085                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2086                              <1> ;;
  2087                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2088                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2089                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2090                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2091                              <1> 
  2092                              <1> ; 27/04/2015
  2093                              <1> ; 09/03/2015
  2094                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2095                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2096                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2097                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2098                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2099                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2100                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2101                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2102                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2103                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2104                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2105                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2106                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2107                              <1> SWP_DISK_READ_ERR 	   equ 40
  2108                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2109                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2110                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2111                              <1> SWP_DISK_WRITE_ERR         equ 44
  2112                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2113                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2114                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2115                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2116                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2117                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2118                              <1> 					; (Indicates that the page is not allocated
  2119                              <1> 					; for the process, it is a shared or system
  2120                              <1>                                         ; page, it must not be deallocated!)
  2121                              <1> ; 14/12/2020
  2122                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2123                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2124                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2125                              <1> 				; (Out of memory allocation table)	
  2126                              <1> ;
  2127                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2128                              <1> ;;
  2129                              <1> ;; 10/10/2014
  2130                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2131                              <1> ;;
  2132                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2133                              <1> ;;	(virtual address = physical address)
  2134                              <1> ;; KERNEL PAGE TABLES:
  2135                              <1> ;;	Kernel page directory and all page tables are
  2136                              <1> ;;	on memory as initialized, as equal to physical memory
  2137                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2138                              <1> ;;
  2139                              <1> ;;	what for: User pages may be swapped out, when accessing
  2140                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2141                              <1> ;;	kernel would have to swap it in! But it is also may be
  2142                              <1> ;;	in use by a user process. (In system/kernel mode
  2143                              <1> ;;	kernel can access all memory pages even if they are
  2144                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2145                              <1> ;;	cause conflicts.) 
  2146                              <1> ;;	
  2147                              <1> ;;	As result of these conditions,
  2148                              <1> ;;	all kernel pages must be initialized as equal to 
  2149                              <1> ;;	physical layout for preventing page faults. 
  2150                              <1> ;;	Also, calling "allocate page" procedure after
  2151                              <1> ;;	a page fault can cause another page fault (double fault)
  2152                              <1> ;;	if all kernel page tables would not be initialized.
  2153                              <1> ;;
  2154                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2155                              <1> ;;	memory allocation table. (double word aligned)
  2156                              <1> ;;
  2157                              <1> ;;	[next_page] = first/next free space to be searched
  2158                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2159                              <1> ;;
  2160                              <1> ;;	[last_page] = End of memory (users space), as offset
  2161                              <1> ;;	to memory allocation table. (double word aligned)
  2162                              <1> ;;
  2163                              <1> ;; USER PAGE TABLES:
  2164                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2165                              <1> ;;		'ready only' marked copies of the 
  2166                              <1> ;;		parent process's page table entries (for
  2167                              <1> ;;		same physical memory).
  2168                              <1> ;;		(A page will be copied to a new page after
  2169                              <1> ;;		 if it causes R/W page fault.)
  2170                              <1> ;;
  2171                              <1> ;;	Every user process has own (different)
  2172                              <1> ;;	page directory and page tables.	
  2173                              <1> ;;
  2174                              <1> ;;	Code starts at virtual address 0, always.
  2175                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2176                              <1> ;;	(Programs can be written/developed as simple
  2177                              <1> ;;	 flat memory programs.)
  2178                              <1> ;;
  2179                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2180                              <1> ;;	Memory page will be allocated by kernel only 
  2181                              <1> ;;		(in kernel/system mode only).
  2182                              <1> ;;	* After a
  2183                              <1> ;;	  - 'not present' page fault
  2184                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2185                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2186                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2187                              <1> ;;	  request by running process.
  2188                              <1> ;;	* While creating a process, allocating a new buffer,
  2189                              <1> ;;	  new page tables etc.
  2190                              <1> ;;
  2191                              <1> ;;	At first,
  2192                              <1> ;;	- 'allocate page' procedure will be called;
  2193                              <1> ;,	   if it will return with a valid (>0) physical address
  2194                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2195                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2196                              <1> ;;	- 'allocate page' will be called for allocating page
  2197                              <1> ;;	   directory, page table and running space (data/code).
  2198                              <1> ;;	- every successful 'allocate page' call will decrease
  2199                              <1> ;;	  'free_pages' count (pointer).
  2200                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2201                              <1> ;;	  if 'free_pages' points to a ZERO.
  2202                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2203                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2204                              <1> ;;	  error except errors caused by attribute conflicts.
  2205                              <1> ;;	 (swapper functions)	 
  2206                              <1> ;;					
  2207                              <1> ;;	At second,
  2208                              <1> ;;	- page directory entry will be updated then page table
  2209                              <1> ;;	  entry will be updated.		
  2210                              <1> ;;
  2211                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2212                              <1> ;;	- M.A.T. has a size according to available memory as
  2213                              <1> ;;	  follows:
  2214                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2215                              <1> ;;		  - a bit with value of 0 means allocated page
  2216                              <1> ;;		  - a bit with value of 1 means a free page
  2217                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2218                              <1> ;;	  depending on M.A.T.
  2219                              <1> ;;		(NOTE: Free page count will not be checked
  2220                              <1> ;;		again -on M.A.T.- after initialization. 
  2221                              <1> ;;		Kernel will trust on initial count.)
  2222                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2223                              <1> ;;	  and it will be increased by deallocation procedures.
  2224                              <1> ;;	
  2225                              <1> ;;	- Available memory will be calculated during
  2226                              <1> ;;	  the kernel's initialization stage (in real mode).
  2227                              <1> ;;	  Memory allocation table and kernel page tables 
  2228                              <1> ;;	  will be formatted/sized as result of available
  2229                              <1> ;;	  memory calculation before paging is enabled.
  2230                              <1> ;;
  2231                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2232                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2233                              <1> ;;	- Memory allocation for kernel page directory size 
  2234                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2235                              <1> ;;	  for page tables)
  2236                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2237                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2238                              <1> ;;	- User (available) space will be started 
  2239                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2240                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2241                              <1> ;;	  memory allocation table and kernel's page directory
  2242                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2243                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2244                              <1> ;; 	  for buffers.
  2245                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2246                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2247                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2248                              <1> ;;
  2249                              <1> ;; For 1GB Available Memory:
  2250                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2251                              <1> ;;	- Memory allocation for kernel page directory size 
  2252                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2253                              <1> ;;	  for page tables)
  2254                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2255                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2256                              <1> ;;	- User (available) space will be started 
  2257                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2258                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2259                              <1> ;;	  memory allocation table and kernel's page directory
  2260                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2261                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2262                              <1> ;; 	  for buffers.
  2263                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2264                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2265                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2266                              <1> ;;
  2267                              <1> ;;
  2268                              <1> 
  2269                              <1> ;;************************************************************************************
  2270                              <1> ;; 
  2271                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2272                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2273                              <1> 
  2274                              <1> ;; Main factor: "sys fork" system call 
  2275                              <1> ;;	
  2276                              <1> ;; 		FORK
  2277                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2278                              <1> ;;  writable pages ---->|
  2279                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2280                              <1> ;; 
  2281                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2282                              <1> ;; 
  2283                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2284                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2285                              <1> ;;       -while R/W bit is 0-. 
  2286                              <1> ;; 
  2287                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2288                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2289                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2290                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2291                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2292                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2293                              <1> ;; 
  2294                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2295                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2296                              <1> ;;   Parent's PTE attributes are not changed.
  2297                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2298                              <1> ;;    destroy/mix previous fork result).
  2299                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2300                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2301                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2302                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2303                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2304                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2305                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2306                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2307                              <1> ;; 
  2308                              <1> ;; !? WHAT FOR (duplication after duplication):
  2309                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2310                              <1> ;; program/executable code continues from specified location as child process, 
  2311                              <1> ;; returns back previous code location as parent process, every child after 
  2312                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2313                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2314                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2315                              <1> ;; was copied to child's process segment (all of code and data) according to
  2316                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2317                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2318                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2319                              <1> ;; (complete running image of parent process) to the child process; 
  2320                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2321                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2322                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2323                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2324                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2325                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2326                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2327                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2328                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2329                              <1> ;; for sharing same read only pages between parent and child processes.
  2330                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2331                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2332                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2333                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2334                              <1> ;; -deallocation problem-.
  2335                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2336                              <1> ;; 
  2337                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2338                              <1> ;; # Page fault handler will do those:
  2339                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2340                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2341                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2342                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2343                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2344                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2345                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2346                              <1> ;;     to child process.)	
  2347                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2348                              <1> ;; # Page fault handler will do those:
  2349                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2350                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2351                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2352                              <1> ;;     address or not. 
  2353                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2354                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2355                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2356                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2357                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2358                              <1> ;; 
  2359                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2360                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2361                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2362                              <1> ;;       duplication method details, it is not possible multiple child processes
  2363                              <1> ;;       were using same page with duplicated PTEs.
  2364                              <1> ;; 
  2365                              <1> ;;************************************************************************************   
  2366                              <1> 
  2367                              <1> ;; 08/10/2014
  2368                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2369                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2370                              <1> 
  2371                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2372                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2373                              <1> ;; (25/08/2014, Revision: 5057) file 
  2374                              <1> ;; by KolibriOS Team (2004-2012)
  2375                              <1> 
  2376                              <1> allocate_page:
  2377                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2378                              <1> 	;	 (temporary modifications)
  2379                              <1> 	; 01/07/2015
  2380                              <1> 	; 05/05/2015
  2381                              <1> 	; 30/04/2015
  2382                              <1> 	; 16/10/2014
  2383                              <1> 	; 08/10/2014
  2384                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2385                              <1> 	;
  2386                              <1> 	; INPUT -> none
  2387                              <1> 	;
  2388                              <1> 	; OUTPUT ->
  2389                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2390                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2391                              <1> 	;
  2392                              <1> 	;	CF = 1 and EAX = 0 
  2393                              <1> 	; 		   if there is not a free page to be allocated	
  2394                              <1> 	;
  2395                              <1> 	; Modified Registers -> none (except EAX)
  2396                              <1> 	;
  2397 00002DA6 A1[906F0000]        <1> 	mov	eax, [free_pages]
  2398 00002DAB 21C0                <1> 	and	eax, eax
  2399 00002DAD 7438                <1> 	jz	short out_of_memory
  2400                              <1> 	;
  2401 00002DAF 53                  <1> 	push	ebx
  2402 00002DB0 51                  <1> 	push	ecx
  2403                              <1> 	;
  2404 00002DB1 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2405 00002DB6 89D9                <1> 	mov	ecx, ebx
  2406                              <1>  				     ; NOTE: 32 (first_page) is initial
  2407                              <1> 				     ; value of [next_page].
  2408                              <1> 				     ; It points to the first available
  2409                              <1> 				     ; page block for users (ring 3) ...	
  2410                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2411                              <1> 				     ; (at the of the first 4 MB)		
  2412 00002DB8 031D[946F0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2413                              <1> 				 ; next_free_page >> 5
  2414 00002DBE 030D[986F0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2415                              <1> 				 ; (total_pages - 1) >> 5
  2416                              <1> al_p_scan:
  2417 00002DC4 39CB                <1> 	cmp	ebx, ecx
  2418 00002DC6 770A                <1> 	ja	short al_p_notfound
  2419                              <1> 	;
  2420                              <1> 	; 01/07/2015
  2421                              <1> 	; AMD64 Architecture Programmers Manual
  2422                              <1> 	; Volume 3:
  2423                              <1> 	; General-Purpose and System Instructions
  2424                              <1> 	;
  2425                              <1> 	; BSF - Bit Scan Forward
  2426                              <1> 	;
  2427                              <1> 	;   Searches the value in a register or a memory location
  2428                              <1> 	;   (second operand) for the least-significant set bit. 
  2429                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2430                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2431                              <1> 	;   register (first operand). If the second operand contains 0, 
  2432                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2433                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2434                              <1> 	;   of the searched value
  2435                              <1> 	;
  2436 00002DC8 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2437                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2438                              <1> 			   ; loads the destination with an index to
  2439                              <1> 			   ; first set bit. (0 -> 31) 
  2440                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2441 00002DCB 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2442                              <1> 			 ;
  2443                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2444                              <1> 			 ;	  with value of 1 means 
  2445                              <1> 			 ;	  the corresponding page is free 
  2446                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2447 00002DCD 83C304              <1> 	add	ebx, 4
  2448                              <1> 			 ; We return back for searching next page block
  2449                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2450                              <1> 			 ;	 we always will find at least 1 free page here.
  2451 00002DD0 EBF2                <1>         jmp     short al_p_scan
  2452                              <1> 	;
  2453                              <1> al_p_notfound:
  2454 00002DD2 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2455 00002DD8 890D[946F0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2456                              <1> 				 ; (deallocate_page procedure will change it)
  2457 00002DDE 31C0                <1> 	xor	eax, eax
  2458 00002DE0 A3[906F0000]        <1> 	mov	[free_pages], eax ; 0
  2459 00002DE5 59                  <1> 	pop	ecx
  2460 00002DE6 5B                  <1> 	pop	ebx
  2461                              <1> 	;
  2462                              <1> ; 17/04/2021
  2463                              <1> ; ('swap_out' procedure call is disabled as temporary)
  2464                              <1> 
  2465                              <1> out_of_memory:
  2466                              <1> ;	call	swap_out
  2467                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2468                              <1> ;	;
  2469                              <1> ;	sub 	eax, eax ; 0
  2470 00002DE7 F9                  <1> 	stc
  2471 00002DE8 C3                  <1> 	retn
  2472                              <1> 
  2473                              <1> al_p_found:
  2474 00002DE9 89D9                <1> 	mov	ecx, ebx
  2475 00002DEB 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2476 00002DF1 890D[946F0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2477                              <1> 				 ; address/offset (to the next)
  2478 00002DF7 FF0D[906F0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2479                              <1> 	;
  2480 00002DFD 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2481                              <1> 				 ; is copied into the Carry Flag and then cleared
  2482                              <1> 				 ; in the destination.
  2483                              <1> 				 ;
  2484                              <1> 				 ; Reset the bit which is corresponding to the 
  2485                              <1> 				 ; (just) allocated page.
  2486                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2487 00002E00 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2488 00002E03 01C8                <1> 	add	eax, ecx	 ; = page number
  2489 00002E05 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2490                              <1> 	; EAX = physical address of memory page
  2491                              <1> 	;
  2492                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2493                              <1> 	;       according to this EAX value...
  2494 00002E08 59                  <1> 	pop	ecx
  2495 00002E09 5B                  <1> 	pop	ebx
  2496                              <1> al_p_ok:
  2497 00002E0A C3                  <1> 	retn
  2498                              <1> 
  2499                              <1> make_page_dir:
  2500                              <1> 	; 18/04/2015
  2501                              <1> 	; 12/04/2015
  2502                              <1> 	; 23/10/2014
  2503                              <1> 	; 16/10/2014
  2504                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2505                              <1> 	;
  2506                              <1> 	; INPUT ->
  2507                              <1> 	;	none
  2508                              <1> 	; OUTPUT ->
  2509                              <1> 	;	(EAX = 0)
  2510                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2511                              <1> 	;	cf = 0 ->
  2512                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2513                              <1> 	;		  process/user.
  2514                              <1> 	;
  2515                              <1> 	; Modified Registers -> EAX
  2516                              <1> 	;
  2517 00002E0B E896FFFFFF          <1> 	call	allocate_page
  2518 00002E10 7216                <1> 	jc	short mkpd_error
  2519                              <1> 	;
  2520 00002E12 A3[08750000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2521                              <1> 				  ; (Physical address)
  2522                              <1> clear_page:
  2523                              <1> 	; 18/04/2015
  2524                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2525                              <1> 	;
  2526                              <1> 	; INPUT ->
  2527                              <1> 	;	EAX = physical address of the page
  2528                              <1> 	; OUTPUT ->
  2529                              <1> 	;	all bytes of the page will be cleared
  2530                              <1> 	;
  2531                              <1> 	; Modified Registers -> none
  2532                              <1> 	;
  2533 00002E17 57                  <1> 	push	edi
  2534 00002E18 51                  <1> 	push	ecx
  2535 00002E19 50                  <1> 	push	eax
  2536 00002E1A B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2537 00002E1F 89C7                <1> 	mov	edi, eax
  2538 00002E21 31C0                <1> 	xor	eax, eax
  2539 00002E23 F3AB                <1> 	rep	stosd
  2540 00002E25 58                  <1> 	pop	eax
  2541 00002E26 59                  <1> 	pop	ecx
  2542 00002E27 5F                  <1> 	pop	edi
  2543                              <1> mkpd_error:
  2544                              <1> mkpt_error:
  2545 00002E28 C3                  <1> 	retn
  2546                              <1> 
  2547                              <1> make_page_table:
  2548                              <1> 	; 23/06/2015
  2549                              <1> 	; 18/04/2015
  2550                              <1> 	; 12/04/2015
  2551                              <1> 	; 16/10/2014
  2552                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2553                              <1> 	;
  2554                              <1> 	; INPUT ->
  2555                              <1> 	;	EBX = virtual (linear) address
  2556                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2557                              <1> 	;	      (higher 20 bits must be ZERO)
  2558                              <1> 	;	      (bit 0 must be 1)	 
  2559                              <1> 	;	u.pgdir = page directory (physical) address
  2560                              <1> 	; OUTPUT ->
  2561                              <1> 	;	EDX = Page directory entry address
  2562                              <1> 	;	EAX = Page table address
  2563                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2564                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2565                              <1> 	;
  2566                              <1> 	; Modified Registers -> EAX, EDX
  2567                              <1> 	;
  2568 00002E29 E878FFFFFF          <1> 	call	allocate_page
  2569 00002E2E 72F8                <1> 	jc	short mkpt_error
  2570 00002E30 E811000000          <1> 	call	set_pde	
  2571 00002E35 EBE0                <1> 	jmp	short clear_page
  2572                              <1> 
  2573                              <1> make_page:
  2574                              <1> 	; 24/07/2015
  2575                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2576                              <1> 	;
  2577                              <1> 	; INPUT ->
  2578                              <1> 	;	EBX = virtual (linear) address
  2579                              <1> 	;	ECX = page attributes (lower 12 bits)
  2580                              <1> 	;	      (higher 20 bits must be ZERO)
  2581                              <1> 	;	      (bit 0 must be 1)	 
  2582                              <1> 	;	u.pgdir = page directory (physical) address
  2583                              <1> 	; OUTPUT ->
  2584                              <1> 	;	EBX = Virtual address
  2585                              <1> 	;	(EDX = PTE value)
  2586                              <1> 	;	EAX = Physical address
  2587                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2588                              <1> 	;
  2589                              <1> 	; Modified Registers -> EAX, EDX
  2590                              <1> 	;
  2591 00002E37 E86AFFFFFF          <1> 	call	allocate_page
  2592 00002E3C 7207                <1> 	jc	short mkp_err
  2593 00002E3E E821000000          <1> 	call	set_pte	
  2594 00002E43 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2595                              <1> mkp_err:
  2596 00002E45 C3                  <1> 	retn
  2597                              <1> 
  2598                              <1> set_pde:	; Set page directory entry (PDE)
  2599                              <1> 	; 20/07/2015
  2600                              <1> 	; 18/04/2015
  2601                              <1> 	; 12/04/2015
  2602                              <1> 	; 23/10/2014
  2603                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2604                              <1> 	;
  2605                              <1> 	; INPUT ->
  2606                              <1> 	;	EAX = physical address
  2607                              <1> 	;	      (use present value if EAX = 0)
  2608                              <1> 	;	EBX = virtual (linear) address
  2609                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2610                              <1> 	;	      (higher 20 bits must be ZERO)
  2611                              <1> 	;	      (bit 0 must be 1)	 
  2612                              <1> 	;	u.pgdir = page directory (physical) address
  2613                              <1> 	; OUTPUT ->
  2614                              <1> 	;	EDX = PDE address
  2615                              <1> 	;	EAX = page table address (physical)
  2616                              <1> 	;	;(CF=1 -> Invalid page address)
  2617                              <1> 	;
  2618                              <1> 	; Modified Registers -> EDX
  2619                              <1> 	;
  2620 00002E46 89DA                <1> 	mov	edx, ebx
  2621 00002E48 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2622 00002E4B C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2623 00002E4E 0315[08750000]      <1> 	add	edx, [u.pgdir]
  2624                              <1> 	;
  2625 00002E54 21C0                <1> 	and	eax, eax
  2626 00002E56 7506                <1> 	jnz	short spde_1
  2627                              <1> 	;
  2628 00002E58 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2629                              <1> 	;test	al, 1
  2630                              <1> 	;jz	short spde_2
  2631 00002E5A 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2632                              <1> spde_1:
  2633                              <1> 	;and	cx, 0FFFh
  2634 00002E5E 8902                <1> 	mov	[edx], eax
  2635 00002E60 66090A              <1> 	or	[edx], cx
  2636 00002E63 C3                  <1> 	retn
  2637                              <1> ;spde_2: ; error
  2638                              <1> ;	stc
  2639                              <1> ;	retn
  2640                              <1> 
  2641                              <1> set_pte:	; Set page table entry (PTE)
  2642                              <1> 	; 24/07/2015
  2643                              <1> 	; 20/07/2015
  2644                              <1> 	; 23/06/2015
  2645                              <1> 	; 18/04/2015
  2646                              <1> 	; 12/04/2015
  2647                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2648                              <1> 	;
  2649                              <1> 	; INPUT ->
  2650                              <1> 	;	EAX = physical page address
  2651                              <1> 	;	      (use present value if EAX = 0)
  2652                              <1> 	;	EBX = virtual (linear) address
  2653                              <1> 	;	ECX = page attributes (lower 12 bits)
  2654                              <1> 	;	      (higher 20 bits must be ZERO)
  2655                              <1> 	;	      (bit 0 must be 1)	 
  2656                              <1> 	;	u.pgdir = page directory (physical) address
  2657                              <1> 	; OUTPUT ->
  2658                              <1> 	;	EAX = physical page address
  2659                              <1> 	;	(EDX = PTE value)
  2660                              <1> 	;	EBX = virtual address
  2661                              <1> 	;
  2662                              <1> 	;	CF = 1 -> error
  2663                              <1> 	;
  2664                              <1> 	; Modified Registers -> EAX, EDX
  2665                              <1> 	;
  2666 00002E64 50                  <1> 	push	eax
  2667 00002E65 A1[08750000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2668 00002E6A E837000000          <1> 	call 	get_pde
  2669                              <1> 		; EDX = PDE address
  2670                              <1> 		; EAX = PDE value
  2671 00002E6F 5A                  <1> 	pop	edx ; physical page address
  2672 00002E70 722A                <1> 	jc	short spte_err ; PDE not present
  2673                              <1> 	;
  2674 00002E72 53                  <1> 	push	ebx ; 24/07/2015
  2675 00002E73 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2676                              <1> 			    ; EDX = PT address (physical)	
  2677 00002E77 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2678 00002E7A 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2679                              <1> 			 ; clear higher 10 bits (PD bits)
  2680 00002E80 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2681 00002E83 01C3                <1> 	add	ebx, eax
  2682                              <1> 	;
  2683 00002E85 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2684 00002E87 A801                <1> 	test	al, 1
  2685 00002E89 740C                <1> 	jz	short spte_0
  2686 00002E8B 09D2                <1> 	or	edx, edx
  2687 00002E8D 750F                <1> 	jnz	short spte_1
  2688 00002E8F 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2689 00002E93 89C2                <1> 	mov	edx, eax
  2690 00002E95 EB09                <1> 	jmp	short spte_2	
  2691                              <1> spte_0:
  2692                              <1> 	; If this PTE contains a swap (disk) address,
  2693                              <1> 	; it can be updated by using 'swap_in' procedure
  2694                              <1> 	; only!
  2695 00002E97 21C0                <1> 	and	eax, eax
  2696 00002E99 7403                <1> 	jz	short spte_1
  2697                              <1> 	; 24/07/2015
  2698                              <1> 	; swapped page ! (on disk)
  2699 00002E9B 5B                  <1> 	pop	ebx
  2700                              <1> spte_err:
  2701 00002E9C F9                  <1> 	stc
  2702 00002E9D C3                  <1> 	retn
  2703                              <1> spte_1: 
  2704 00002E9E 89D0                <1> 	mov	eax, edx
  2705                              <1> spte_2:
  2706 00002EA0 09CA                <1> 	or	edx, ecx
  2707                              <1> 	; 23/06/2015
  2708 00002EA2 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2709                              <1> 	; 24/07/2015
  2710 00002EA4 5B                  <1> 	pop	ebx
  2711 00002EA5 C3                  <1> 	retn
  2712                              <1> 
  2713                              <1> get_pde:	; Get present value of the relevant PDE
  2714                              <1> 	; 20/07/2015
  2715                              <1> 	; 18/04/2015
  2716                              <1> 	; 12/04/2015
  2717                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2718                              <1> 	;
  2719                              <1> 	; INPUT ->
  2720                              <1> 	;	EBX = virtual (linear) address
  2721                              <1> 	;	EAX = page directory (physical) address
  2722                              <1> 	; OUTPUT ->
  2723                              <1> 	;	EDX = Page directory entry address
  2724                              <1> 	;	EAX = Page directory entry value
  2725                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2726                              <1> 	; Modified Registers -> EDX, EAX
  2727                              <1> 	;
  2728 00002EA6 89DA                <1> 	mov	edx, ebx
  2729 00002EA8 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2730 00002EAB C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2731 00002EAE 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2732 00002EB0 8B02                <1> 	mov	eax, [edx]
  2733 00002EB2 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2734 00002EB4 751F                <1> 	jnz	short gpte_retn
  2735 00002EB6 F9                  <1> 	stc
  2736                              <1> gpde_retn:	
  2737 00002EB7 C3                  <1> 	retn
  2738                              <1> 
  2739                              <1> get_pte:
  2740                              <1> 		; Get present value of the relevant PTE
  2741                              <1> 	; 29/07/2015
  2742                              <1> 	; 20/07/2015
  2743                              <1> 	; 18/04/2015
  2744                              <1> 	; 12/04/2015
  2745                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2746                              <1> 	;
  2747                              <1> 	; INPUT ->
  2748                              <1> 	;	EBX = virtual (linear) address
  2749                              <1> 	;	EAX = page directory (physical) address
  2750                              <1> 	; OUTPUT ->
  2751                              <1> 	;	EDX = Page table entry address (if CF=0)
  2752                              <1> 	;	      Page directory entry address (if CF=1)
  2753                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2754                              <1> 	;	EAX = Page table entry value (page address)
  2755                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2756                              <1> 	; Modified Registers -> EAX, EDX
  2757                              <1> 	;
  2758 00002EB8 E8E9FFFFFF          <1> 	call 	get_pde
  2759 00002EBD 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2760                              <1> 	;jnc	short gpte_1
  2761                              <1> 	;retn
  2762                              <1> ;gpte_1:
  2763 00002EBF 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2764 00002EC3 89DA                <1> 	mov	edx, ebx
  2765 00002EC5 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2766 00002EC8 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2767                              <1> 			 ; clear higher 10 bits (PD bits)
  2768 00002ECE C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2769 00002ED1 01C2                <1> 	add	edx, eax
  2770 00002ED3 8B02                <1> 	mov	eax, [edx]
  2771                              <1> gpte_retn:
  2772 00002ED5 C3                  <1> 	retn
  2773                              <1> 
  2774                              <1> deallocate_page_dir:
  2775                              <1> 	; 15/09/2015
  2776                              <1> 	; 05/08/2015
  2777                              <1> 	; 30/04/2015
  2778                              <1> 	; 28/04/2015
  2779                              <1> 	; 17/10/2014
  2780                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2781                              <1> 	;
  2782                              <1> 	; INPUT ->
  2783                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2784                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2785                              <1> 	; OUTPUT ->
  2786                              <1> 	;	All of page tables in the page directory
  2787                              <1> 	;	and page dir's itself will be deallocated
  2788                              <1> 	;	except 'read only' duplicated pages (will be converted
  2789                              <1> 	;	to writable pages).
  2790                              <1> 	;
  2791                              <1> 	; Modified Registers -> EAX
  2792                              <1> 	;
  2793                              <1> 	;
  2794 00002ED6 56                  <1> 	push	esi
  2795 00002ED7 51                  <1> 	push	ecx
  2796 00002ED8 50                  <1> 	push	eax
  2797 00002ED9 89C6                <1> 	mov	esi, eax 
  2798 00002EDB 31C9                <1> 	xor	ecx, ecx
  2799                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2800                              <1> 	; it must not be deallocated
  2801 00002EDD 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2802                              <1> dapd_0:
  2803 00002EDF AD                  <1> 	lodsd
  2804 00002EE0 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2805 00002EE2 7409                <1> 	jz	short dapd_1	
  2806 00002EE4 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2807 00002EE8 E812000000          <1> 	call	deallocate_page_table			
  2808                              <1> dapd_1:
  2809 00002EED 41                  <1> 	inc	ecx ; page directory entry index
  2810 00002EEE 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2811 00002EF4 72E9                <1> 	jb	short dapd_0
  2812                              <1> dapd_2:
  2813 00002EF6 58                  <1> 	pop	eax
  2814 00002EF7 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2815 00002EFC 59                  <1> 	pop	ecx
  2816 00002EFD 5E                  <1> 	pop	esi
  2817 00002EFE C3                  <1> 	retn
  2818                              <1> 
  2819                              <1> deallocate_page_table:
  2820                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2821                              <1> 	;	 (temporary modifications)
  2822                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2823                              <1> 	; 19/09/2015
  2824                              <1> 	; 15/09/2015
  2825                              <1> 	; 05/08/2015
  2826                              <1> 	; 30/04/2015
  2827                              <1> 	; 28/04/2015
  2828                              <1> 	; 24/10/2014
  2829                              <1> 	; 23/10/2014
  2830                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2831                              <1> 	;
  2832                              <1> 	; INPUT ->
  2833                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2834                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2835                              <1> 	;	(ECX = page directory entry index)
  2836                              <1> 	; OUTPUT ->
  2837                              <1> 	;	All of pages in the page table and page table's itself
  2838                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2839                              <1> 	;	(will be converted to writable pages).
  2840                              <1> 	;
  2841                              <1> 	; Modified Registers -> EAX
  2842                              <1> 	;
  2843 00002EFF 56                  <1> 	push	esi
  2844 00002F00 57                  <1> 	push	edi
  2845 00002F01 52                  <1> 	push	edx
  2846 00002F02 50                  <1> 	push	eax ; *
  2847 00002F03 89C6                <1> 	mov	esi, eax 
  2848 00002F05 31FF                <1> 	xor	edi, edi ; 0
  2849                              <1> dapt_0:
  2850 00002F07 AD                  <1> 	lodsd
  2851 00002F08 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2852 00002F0A 7455                <1> 	jz	short dapt_1
  2853                              <1> 	;
  2854 00002F0C A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2855                              <1> 				  ; (must be 1)
  2856 00002F0E 753F                <1> 	jnz	short dapt_3
  2857                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2858 00002F10 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2859                              <1> 				   ; as child's page ?
  2860 00002F14 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2861                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2862                              <1> 	; ECX = page directory entry index (0-1023)
  2863 00002F16 53                  <1> 	push	ebx
  2864 00002F17 51                  <1> 	push	ecx
  2865 00002F18 66C1E102            <1> 	shl	cx, 2 ; *4 
  2866 00002F1C 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2867 00002F1E 8B0B                <1> 	mov	ecx, [ebx]
  2868 00002F20 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2869 00002F23 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2870 00002F25 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2871                              <1> 	; EDI = page table entry index (0-1023)
  2872 00002F2A 89FA                <1> 	mov	edx, edi 
  2873 00002F2C 66C1E202            <1> 	shl	dx, 2 ; *4 
  2874 00002F30 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2875 00002F32 8B1A                <1> 	mov	ebx, [edx]
  2876 00002F34 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2877 00002F37 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2878 00002F39 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2879 00002F3D 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2880 00002F42 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2881 00002F44 7507                <1> 	jne	short dapt_2	; not same page
  2882                              <1> 				; deallocate the child's page
  2883 00002F46 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2884 00002F49 59                  <1> 	pop	ecx
  2885 00002F4A 5B                  <1> 	pop	ebx
  2886 00002F4B EB0D                <1> 	jmp	short dapt_4
  2887                              <1> 
  2888                              <1> ; 17/04/2021
  2889                              <1> ; ('dapt_1' is disabled as temporary)
  2890                              <1> ;
  2891                              <1> ;dapt_1:
  2892                              <1> ;	or	eax, eax	; swapped page ?
  2893                              <1> ;	jz	short dapt_5	; no
  2894                              <1> ;				; yes
  2895                              <1> ;	shr	eax, 1
  2896                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2897                              <1> ;				  ; on the swap disk (or in file)
  2898                              <1> ;	jmp	short dapt_5
  2899                              <1> dapt_2:
  2900 00002F4D 59                  <1> 	pop	ecx
  2901 00002F4E 5B                  <1> 	pop	ebx
  2902                              <1> dapt_3:	
  2903                              <1> 	; 12/07/2016
  2904 00002F4F 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2905 00002F53 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2906                              <1> 	;
  2907                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2908 00002F55 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2909                              <1> dapt_4:
  2910 00002F5A C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2911                              <1> dapt_1:	; 17/04/2021 (temporary)
  2912                              <1> dapt_5:
  2913 00002F61 47                  <1> 	inc	edi ; page table entry index
  2914 00002F62 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2915 00002F68 729D                <1> 	jb	short dapt_0
  2916                              <1> 	;
  2917 00002F6A 58                  <1> 	pop	eax ; *
  2918 00002F6B 5A                  <1> 	pop	edx
  2919 00002F6C 5F                  <1> 	pop	edi	
  2920 00002F6D 5E                  <1> 	pop	esi
  2921                              <1> 	;
  2922                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2923                              <1> 	;retn
  2924                              <1> 
  2925                              <1> deallocate_page:
  2926                              <1> 	; 15/09/2015
  2927                              <1> 	; 28/04/2015
  2928                              <1> 	; 10/03/2015
  2929                              <1> 	; 17/10/2014
  2930                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2931                              <1> 	;
  2932                              <1> 	; INPUT -> 
  2933                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2934                              <1> 	; OUTPUT ->
  2935                              <1> 	;	[free_pages] is increased
  2936                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2937                              <1> 	;	CF = 1 if the page is already deallocated
  2938                              <1> 	; 	       (or not allocated) before.  
  2939                              <1> 	;
  2940                              <1> 	; Modified Registers -> EAX
  2941                              <1> 	;
  2942 00002F6E 53                  <1> 	push	ebx
  2943 00002F6F 52                  <1> 	push	edx
  2944                              <1> 	;
  2945 00002F70 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2946                              <1> 				     ; 12 bits right
  2947                              <1> 				     ; to get page number
  2948 00002F73 89C2                <1> 	mov	edx, eax
  2949                              <1> 	; 15/09/2015
  2950 00002F75 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2951                              <1> 				     ; (1 allocation bit = 1 page)
  2952                              <1> 				     ; (1 allocation bytes = 8 pages)
  2953 00002F78 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2954                              <1> 				     ; (to get 32 bit position)			
  2955                              <1> 	;
  2956 00002F7B BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2957 00002F80 01D3                <1> 	add	ebx, edx
  2958 00002F82 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2959                              <1> 				     ; (allocation bit position)	 
  2960 00002F85 3B15[946F0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2961                              <1> 				     ; than the address in 'next_page' ?
  2962                              <1> 				     ; (next/first free page value)		
  2963 00002F8B 7306                <1> 	jnb	short dap_1	     ; no	
  2964 00002F8D 8915[946F0000]      <1> 	mov	[next_page], edx     ; yes
  2965                              <1> dap_1:
  2966 00002F93 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2967                              <1> 				     ; set relevant bit to 1.
  2968                              <1> 				     ; set CF to the previous bit value	
  2969                              <1> 	;cmc			     ; complement carry flag	
  2970                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2971                              <1> 				     ; if the page is already deallocated
  2972                              <1> 				     ; before.	
  2973 00002F96 FF05[906F0000]      <1>         inc     dword [free_pages]
  2974                              <1> dap_2:
  2975 00002F9C 5A                  <1> 	pop	edx
  2976 00002F9D 5B                  <1> 	pop	ebx
  2977 00002F9E C3                  <1> 	retn
  2978                              <1> 
  2979                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2980                              <1> ;;                                                              ;;
  2981                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2982                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2983                              <1> ;;                                                              ;;
  2984                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2985                              <1> 
  2986                              <1> ;;$Revision: 5057 $
  2987                              <1> 
  2988                              <1> 
  2989                              <1> ;;align 4
  2990                              <1> ;;proc alloc_page
  2991                              <1> 
  2992                              <1> ;;        pushfd
  2993                              <1> ;;        cli
  2994                              <1> ;;        push    ebx
  2995                              <1> ;;;//-
  2996                              <1> ;;        cmp     [pg_data.pages_free], 1
  2997                              <1> ;;        jle     .out_of_memory
  2998                              <1> ;;;//-
  2999                              <1> ;;
  3000                              <1> ;;        mov     ebx, [page_start]
  3001                              <1> ;;        mov     ecx, [page_end]
  3002                              <1> ;;.l1:
  3003                              <1> ;;        bsf     eax, [ebx];
  3004                              <1> ;;        jnz     .found
  3005                              <1> ;;        add     ebx, 4
  3006                              <1> ;;        cmp     ebx, ecx
  3007                              <1> ;;        jb      .l1
  3008                              <1> ;;        pop     ebx
  3009                              <1> ;;        popfd
  3010                              <1> ;;        xor     eax, eax
  3011                              <1> ;;        ret
  3012                              <1> ;;.found:
  3013                              <1> ;;;//-
  3014                              <1> ;;        dec     [pg_data.pages_free]
  3015                              <1> ;;        jz      .out_of_memory
  3016                              <1> ;;;//-
  3017                              <1> ;;        btr     [ebx], eax
  3018                              <1> ;;        mov     [page_start], ebx
  3019                              <1> ;;        sub     ebx, sys_pgmap
  3020                              <1> ;;        lea     eax, [eax+ebx*8]
  3021                              <1> ;;        shl     eax, 12
  3022                              <1> ;;;//-       dec [pg_data.pages_free]
  3023                              <1> ;;        pop     ebx
  3024                              <1> ;;        popfd
  3025                              <1> ;;        ret
  3026                              <1> ;;;//-
  3027                              <1> ;;.out_of_memory:
  3028                              <1> ;;        mov     [pg_data.pages_free], 1
  3029                              <1> ;;        xor     eax, eax
  3030                              <1> ;;        pop     ebx
  3031                              <1> ;;        popfd
  3032                              <1> ;;        ret
  3033                              <1> ;;;//-
  3034                              <1> ;;endp
  3035                              <1> 
  3036                              <1> duplicate_page_dir:
  3037                              <1> 	; 21/09/2015
  3038                              <1> 	; 31/08/2015
  3039                              <1> 	; 20/07/2015
  3040                              <1> 	; 28/04/2015
  3041                              <1> 	; 27/04/2015
  3042                              <1> 	; 18/04/2015
  3043                              <1> 	; 12/04/2015
  3044                              <1> 	; 18/10/2014
  3045                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3046                              <1> 	;
  3047                              <1> 	; INPUT -> 
  3048                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3049                              <1> 	;		    page directory.
  3050                              <1> 	; OUTPUT ->
  3051                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3052                              <1> 	;	       page directory.
  3053                              <1> 	;	(New page directory with new page table entries.)
  3054                              <1> 	;	(New page tables with read only copies of the parent's
  3055                              <1> 	;	pages.)
  3056                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3057                              <1> 	;
  3058                              <1> 	; Modified Registers -> none (except EAX)
  3059                              <1> 	;
  3060 00002F9F E802FEFFFF          <1> 	call	allocate_page
  3061 00002FA4 723E                <1> 	jc	short dpd_err
  3062                              <1> 	;
  3063 00002FA6 55                  <1> 	push	ebp ; 20/07/2015
  3064 00002FA7 56                  <1> 	push	esi
  3065 00002FA8 57                  <1> 	push	edi
  3066 00002FA9 53                  <1> 	push	ebx
  3067 00002FAA 51                  <1> 	push	ecx
  3068 00002FAB 8B35[08750000]      <1> 	mov	esi, [u.pgdir]
  3069 00002FB1 89C7                <1> 	mov	edi, eax
  3070 00002FB3 50                  <1> 	push	eax ; save child's page directory address
  3071                              <1> 	; 31/08/2015
  3072                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3073                              <1> 	; (use same system space for all user page tables) 
  3074 00002FB4 A5                  <1> 	movsd
  3075 00002FB5 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3076 00002FBA B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3077                              <1> dpd_0:	
  3078 00002FBF AD                  <1> 	lodsd
  3079                              <1> 	;or	eax, eax
  3080                              <1>         ;jnz     short dpd_1
  3081 00002FC0 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3082 00002FC2 7508                <1> 	jnz	short dpd_1
  3083                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3084 00002FC4 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3085 00002FCA EB0F                <1> 	jmp	short dpd_2
  3086                              <1> dpd_1:	
  3087 00002FCC 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3088 00002FD0 89C3                <1> 	mov	ebx, eax
  3089                              <1> 	; EBX = Parent's page table address
  3090 00002FD2 E81F000000          <1> 	call	duplicate_page_table
  3091 00002FD7 720C                <1> 	jc	short dpd_p_err
  3092                              <1> 	; EAX = Child's page table address
  3093 00002FD9 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3094                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3095                              <1> 			 ; (present, writable, user)
  3096                              <1> dpd_2:
  3097 00002FDB AB                  <1> 	stosd
  3098 00002FDC E2E1                <1> 	loop	dpd_0
  3099                              <1> 	;
  3100 00002FDE 58                  <1> 	pop	eax  ; restore child's page directory address
  3101                              <1> dpd_3:
  3102 00002FDF 59                  <1> 	pop	ecx
  3103 00002FE0 5B                  <1> 	pop	ebx
  3104 00002FE1 5F                  <1> 	pop	edi
  3105 00002FE2 5E                  <1> 	pop	esi
  3106 00002FE3 5D                  <1> 	pop	ebp ; 20/07/2015
  3107                              <1> dpd_err:
  3108 00002FE4 C3                  <1> 	retn
  3109                              <1> dpd_p_err:
  3110                              <1> 	; release the allocated pages missing (recover free space)
  3111 00002FE5 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3112 00002FE6 8B1D[08750000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3113 00002FEC E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3114 00002FF1 29C0                <1> 	sub	eax, eax ; 0
  3115 00002FF3 F9                  <1> 	stc
  3116 00002FF4 EBE9                <1> 	jmp	short dpd_3	
  3117                              <1> 
  3118                              <1> duplicate_page_table:
  3119                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3120                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3121                              <1> 	;	 (temporary modifications)
  3122                              <1> 	; 16/04/2021 (Retro UNIX 386 v2)
  3123                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3124                              <1> 	; 21/09/2015
  3125                              <1> 	; 20/07/2015
  3126                              <1> 	; 05/05/2015
  3127                              <1> 	; 28/04/2015
  3128                              <1> 	; 27/04/2015
  3129                              <1> 	; 18/04/2015
  3130                              <1> 	; 18/10/2014
  3131                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3132                              <1> 	;
  3133                              <1> 	; INPUT -> 
  3134                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3135                              <1> 	;       20/02/2017		 
  3136                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3137                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3138                              <1> 	; OUTPUT ->
  3139                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3140                              <1> 	;	      (with 'read only' attribute of page table entries)
  3141                              <1> 	;	20/02/2017
  3142                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3143                              <1> 	;	
  3144                              <1> 	;	CF = 1 -> error 
  3145                              <1> 	;
  3146                              <1> 	; Modified Registers -> EBP (except EAX)
  3147                              <1> 	;
  3148 00002FF6 E8ABFDFFFF          <1> 	call	allocate_page
  3149 00002FFB 725B                <1> 	jc	short dpt_err
  3150                              <1> 	;
  3151 00002FFD 50                  <1> 	push	eax ; *
  3152 00002FFE 56                  <1> 	push	esi
  3153 00002FFF 57                  <1> 	push	edi
  3154 00003000 52                  <1> 	push	edx
  3155 00003001 51                  <1> 	push	ecx
  3156                              <1> 	;
  3157 00003002 89DE                <1> 	mov	esi, ebx
  3158 00003004 89C7                <1> 	mov	edi, eax
  3159 00003006 89C2                <1> 	mov	edx, eax
  3160 00003008 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3161                              <1> dpt_0:
  3162 0000300E AD                  <1> 	lodsd
  3163 0000300F 21C0                <1> 	and	eax, eax
  3164 00003011 7435                <1> 	jz	short dpt_3
  3165 00003013 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3166                              <1> 	; 17/04/2021 (temporary)
  3167 00003015 7503                <1> 	jnz	short dpt_1
  3168                              <1> 	;jz	short dpt_p_err
  3169                              <1> 	; 31/12/2021
  3170 00003017 F9                  <1> 	stc
  3171 00003018 EB39                <1> 	jmp	short dpt_p_err
  3172                              <1> 
  3173                              <1> ; 17/04/2021
  3174                              <1> ; ('reload_page' procedure call is disabled as temporary)
  3175                              <1> ;
  3176                              <1> ;	; 20/07/2015
  3177                              <1> ;	; ebp = virtual (linear) address of the memory page
  3178                              <1> ;	call	reload_page ; 28/04/2015
  3179                              <1> ;	jc	short dpt_p_err
  3180                              <1> dpt_1:
  3181                              <1> 	; 21/09/2015
  3182 0000301A 89C1                <1> 	mov	ecx, eax
  3183 0000301C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3184 00003020 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3185 00003023 751A                <1> 	jnz	short dpt_2
  3186                              <1> 	; Read only (parent) page
  3187                              <1> 	; 	- there is a third process which uses this page -
  3188                              <1> 	; Allocate a new page for the child process
  3189 00003025 E87CFDFFFF          <1> 	call	allocate_page
  3190 0000302A 7227                <1> 	jc	short dpt_p_err
  3191 0000302C 57                  <1> 	push	edi
  3192 0000302D 56                  <1> 	push	esi
  3193 0000302E 89CE                <1> 	mov	esi, ecx
  3194 00003030 89C7                <1> 	mov	edi, eax
  3195 00003032 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3196 00003037 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3197 00003039 5E                  <1> 	pop	esi
  3198 0000303A 5F                  <1> 	pop	edi
  3199                              <1> 	;
  3200                              <1> 
  3201                              <1> ; 17/04/2021
  3202                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  3203                              <1> ; 
  3204                              <1> ;	push	ebx
  3205                              <1> ;	push	eax
  3206                              <1> ;	; 20/07/2015
  3207                              <1> ;	mov	ebx, ebp
  3208                              <1> ;	; ebx = virtual (linear) address of the memory page
  3209                              <1> ;	call	add_to_swap_queue
  3210                              <1> ;	pop	eax
  3211                              <1> ;	pop	ebx
  3212                              <1> 
  3213                              <1> 	; 21/09/2015
  3214 0000303B 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3215                              <1> 		; user + writable + present page
  3216 0000303D EB09                <1> 	jmp	short dpt_3
  3217                              <1> dpt_2:
  3218                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3219 0000303F 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3220                              <1> 		    ; (read only page!)
  3221 00003041 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3222 00003044 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3223                              <1> dpt_3:
  3224 00003048 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3225                              <1> 	;
  3226 00003049 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3227                              <1> 	;
  3228 0000304F 39D7                <1> 	cmp	edi, edx
  3229 00003051 72BB                <1> 	jb	short dpt_0
  3230                              <1> dpt_p_err:
  3231 00003053 59                  <1> 	pop	ecx
  3232 00003054 5A                  <1> 	pop	edx
  3233 00003055 5F                  <1> 	pop	edi
  3234 00003056 5E                  <1> 	pop	esi
  3235 00003057 58                  <1> 	pop	eax ; *
  3236                              <1> dpt_err:
  3237 00003058 C3                  <1> 	retn
  3238                              <1> 
  3239                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3240                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3241                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3242                              <1> 	;	 (temporary modifications)
  3243                              <1> 	; 21/09/2015
  3244                              <1> 	; 19/09/2015
  3245                              <1> 	; 17/09/2015
  3246                              <1> 	; 28/08/2015
  3247                              <1> 	; 20/07/2015
  3248                              <1> 	; 28/06/2015
  3249                              <1> 	; 03/05/2015
  3250                              <1> 	; 30/04/2015
  3251                              <1> 	; 18/04/2015
  3252                              <1> 	; 12/04/2015
  3253                              <1> 	; 30/10/2014
  3254                              <1> 	; 11/09/2014
  3255                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3256                              <1> 	;
  3257                              <1> 	; Note: This is not an interrupt/exception handler.
  3258                              <1> 	;	This is a 'page fault remedy' subroutine 
  3259                              <1> 	;	which will be called by standard/uniform
  3260                              <1> 	;	exception handler.
  3261                              <1> 	;
  3262                              <1> 	; INPUT -> 
  3263                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3264                              <1> 	;
  3265                              <1> 	;	cr2 = the virtual (linear) address 
  3266                              <1> 	;	      which has caused to page fault (19/09/2015)
  3267                              <1> 	;
  3268                              <1> 	; OUTPUT ->
  3269                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3270                              <1> 	;	EAX = 0 -> no error
  3271                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3272                              <1> 	;
  3273                              <1> 	; Modified Registers -> none (except EAX)
  3274                              <1> 	;	
  3275                              <1>         ;
  3276                              <1>         ; ERROR CODE:
  3277                              <1> 	;	 31  .....	4   3	2   1	0
  3278                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3279                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3280                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3281                              <1> 	;
  3282                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3283                              <1>     	;		a page-protection violation. When not set,
  3284                              <1> 	;		it was caused by a non-present page.
  3285                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3286                              <1> 	;		a page write. When not set, it was caused
  3287                              <1> 	;		by a page read.
  3288                              <1> 	; U : USER    -	When set, the page fault was caused 
  3289                              <1> 	;		while CPL = 3. 
  3290                              <1> 	;		This does not necessarily mean that
  3291                              <1> 	;		the page fault was a privilege violation.
  3292                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3293                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3294                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3295                              <1> 	;     FETCH	an instruction fetch
  3296                              <1> 	;
  3297                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3298                              <1> 	;  31               22                  12 11                    0
  3299                              <1> 	; +-------------------+-------------------+-----------------------+
  3300                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3301                              <1>        	; +-------------------+-------------------+-----------------------+
  3302                              <1> 	;
  3303                              <1> 
  3304                              <1> 	;; CR3 REGISTER (Control Register 3)
  3305                              <1> 	;  31                                   12             5 4 3 2   0
  3306                              <1> 	; +---------------------------------------+-------------+---+-----+
  3307                              <1>       	; |                                       |  		|P|P|     |
  3308                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3309                              <1>       	; |                                       | 		|D|T|     |
  3310                              <1>    	; +---------------------------------------+-------------+---+-----+
  3311                              <1> 	;
  3312                              <1> 	;	PWT    - WRITE THROUGH
  3313                              <1> 	;	PCD    - CACHE DISABLE		
  3314                              <1> 	;
  3315                              <1> 	;
  3316                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3317                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3318                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3319                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3320                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3321                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3322                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3323                              <1> 	;
  3324                              <1>         ;       P      - PRESENT
  3325                              <1>         ;       R/W    - READ/WRITE
  3326                              <1>         ;       U/S    - USER/SUPERVISOR
  3327                              <1> 	;	PWT    - WRITE THROUGH
  3328                              <1> 	;	PCD    - CACHE DISABLE	
  3329                              <1> 	;	A      - ACCESSED	
  3330                              <1>         ;       D      - DIRTY (IGNORED)
  3331                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3332                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3333                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3334                              <1> 	;
  3335                              <1> 	;
  3336                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3337                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3338                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3339                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3340                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3341                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3342                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3343                              <1> 	;
  3344                              <1>         ;       P      - PRESENT
  3345                              <1>         ;       R/W    - READ/WRITE
  3346                              <1>         ;       U/S    - USER/SUPERVISOR
  3347                              <1> 	;	PWT    - WRITE THROUGH
  3348                              <1> 	;	PCD    - CACHE DISABLE	
  3349                              <1> 	;	A      - ACCESSED	
  3350                              <1>         ;       D      - DIRTY
  3351                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3352                              <1> 	;	G      - GLOBAL	 
  3353                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3354                              <1> 	;
  3355                              <1> 	;
  3356                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3357                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3358                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3359                              <1>       	; |                                       |     | | | | | | |U|R| |
  3360                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3361                              <1>       	; |                                       |     | | | | | | |S|W| |
  3362                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3363                              <1> 	;
  3364                              <1>         ;       P      - PRESENT
  3365                              <1>         ;       R/W    - READ/WRITE
  3366                              <1>         ;       U/S    - USER/SUPERVISOR
  3367                              <1>         ;       D      - DIRTY
  3368                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3369                              <1> 	;
  3370                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3371                              <1> 	;
  3372                              <1> 	;
  3373                              <1> 	;; Invalid Page Table Entry
  3374                              <1> 	; 31                                                           1 0
  3375                              <1>       	; +-------------------------------------------------------------+-+
  3376                              <1>       	; |                                                             | |
  3377                              <1>       	; |                          AVAILABLE                          |0|
  3378                              <1>       	; |                                                             | |
  3379                              <1>       	; +-------------------------------------------------------------+-+
  3380                              <1> 	;
  3381                              <1> 
  3382 00003059 53                  <1> 	push	ebx
  3383 0000305A 52                  <1> 	push	edx
  3384 0000305B 51                  <1> 	push	ecx
  3385                              <1> 	;
  3386                              <1> 	; 21/09/2015 (debugging)
  3387 0000305C FF05[20750000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3388 00003062 FF05[40700000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3389                              <1> 	; 28/06/2015
  3390                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3391 00003068 8A15[38700000]      <1> 	mov	dl, [error_code]
  3392                              <1> 	;
  3393 0000306E F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3394                              <1> 			; sign
  3395 00003071 7416                <1> 	jz	short pfh_alloc_np
  3396                              <1> 	; 
  3397                              <1> 	; If it is not a 'write on read only page' type page fault
  3398                              <1> 	; major page fault error with minor reason must be returned without 
  3399                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3400                              <1> 	; after return here!
  3401                              <1> 	; Page fault will be remedied, by copying page contents
  3402                              <1> 	; to newly allocated page with write permission;
  3403                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3404                              <1> 	; used for working with minimum possible memory usage. 
  3405                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3406                              <1> 	; process with 'read only' flag. If the child process attempts to
  3407                              <1> 	; write on these read only pages, page fault will be directed here
  3408                              <1> 	; for allocating a new page with same data/content. 
  3409                              <1> 	;
  3410                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3411                              <1> 	; will not force to separate CODE and DATA space 
  3412                              <1> 	; in a process/program... 
  3413                              <1> 	; CODE segment/section may contain DATA!
  3414                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3415                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3416                              <1> 	;	
  3417 00003073 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3418                              <1> 			; sign
  3419 00003076 744F                <1>         jz	short pfh_p_err
  3420                              <1> 	; 31/08/2015
  3421 00003078 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3422                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3423 0000307B 744A                <1>         jz	short pfh_pv_err
  3424                              <1> 	;
  3425                              <1> 	; make a new page and copy the parent's page content
  3426                              <1> 	; as the child's new page content
  3427                              <1> 	;
  3428 0000307D 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3429                              <1> 			 ; which has caused to page fault
  3430 00003080 E87C000000          <1> 	call 	copy_page
  3431 00003085 7239                <1>         jc	short pfh_im_err ; insufficient memory
  3432                              <1> 	;
  3433 00003087 EB72                <1>         jmp     pfh_cpp_ok
  3434                              <1> 	;
  3435                              <1> pfh_alloc_np:
  3436 00003089 E818FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3437 0000308E 7230                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3438                              <1> pfh_chk_cpl:
  3439                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3440                              <1> 		; (Lower 12 bits are ZERO, because 
  3441                              <1> 		;	the address is on a page boundary)
  3442 00003090 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3443 00003093 7505                <1> 	jnz	short pfh_um
  3444                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3445 00003095 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3446                              <1> 			 ; of the current/active page directory
  3447                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3448                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3449 00003098 EB06                <1> 	jmp	short pfh_get_pde
  3450                              <1> 	;
  3451                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3452 0000309A 8B1D[08750000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3453                              <1> 			; Physical address of the USER's page directory
  3454                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3455                              <1> pfh_get_pde:
  3456 000030A0 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3457 000030A3 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3458                              <1> 			 ; which has been caused to page fault
  3459                              <1> 			 ;
  3460 000030A6 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3461 000030A9 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3462                              <1> 	;
  3463 000030AC 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3464 000030AE 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3465 000030B0 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3466 000030B3 741A                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3467                              <1> 			  	  ; set/validate page directory entry
  3468 000030B5 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3469 000030BA 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3470 000030BC 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3471 000030BE EB25                <1> 	jmp	short pfh_get_pte
  3472                              <1> 
  3473                              <1> 	; 31/12/2021 (short jump)
  3474                              <1> pfh_im_err:
  3475 000030C0 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3476                              <1> 			; Major (Primary) Error: Page Fault
  3477                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3478 000030C5 EB36                <1> 	jmp	short pfh_err_retn
  3479                              <1> 
  3480                              <1> 	; 31/12/2021
  3481                              <1> pfh_p_err: ; 09/03/2015
  3482                              <1> pfh_pv_err:
  3483                              <1> 	; Page fault was caused by a protection-violation
  3484 000030C7 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3485                              <1> 			; Major (Primary) Error: Page Fault
  3486                              <1> 			; Minor (Secondary) Error: Protection violation !
  3487 000030CC F9                  <1> 	stc
  3488 000030CD EB2E                <1> 	jmp	short pfh_err_retn
  3489                              <1> 
  3490                              <1> pfh_set_pde:
  3491                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3492                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3493                              <1> 	;
  3494 000030CF 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3495 000030D1 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3496 000030D3 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3497 000030D5 89C3                <1> 	mov	ebx, eax
  3498 000030D7 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3499 000030DC 72E2                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3500                              <1> pfh_spde_1:
  3501                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3502 000030DE 89C1                <1> 	mov	ecx, eax
  3503 000030E0 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3504                              <1> pfh_get_pte:
  3505 000030E5 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3506                              <1> 			 ; which has been caused to page fault
  3507 000030E8 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3508 000030EA C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3509                              <1> 			 ; higher 20 bits of the page fault address 
  3510 000030ED 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3511 000030F2 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3512 000030F5 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3513                              <1> ; 17/04/2021 temporary
  3514                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3515                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3516                              <1> ; 17/04/2021
  3517                              <1> ; ('swap_in' procedure call has been disabled as temporary)
  3518                              <1> ;
  3519                              <1> ;	and	eax, eax
  3520                              <1> ;	jz	short pfh_gpte_1
  3521                              <1> ;	; 20/07/2015
  3522                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3523                              <1> ;	push	ebp ; 20/07/2015
  3524                              <1> ;	mov	ebp, cr2
  3525                              <1> ;		; ECX = physical address of the page table entry
  3526                              <1> ;		; EBX = Memory page address (physical!)
  3527                              <1> ;		; EAX = Swap disk (offset) address
  3528                              <1> ;		; EBP = virtual address (page fault address)
  3529                              <1> ;	call	swap_in
  3530                              <1> ;	pop	ebp
  3531                              <1> ;	jc      short pfh_err_retn
  3532                              <1> ;	xchg	ecx, ebx
  3533                              <1> ;		; EBX = physical address of the page table entry
  3534                              <1> ;		; ECX = new page
  3535                              <1> pfh_gpte_1:
  3536 000030F7 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3537 000030F9 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3538                              <1> pfh_cpp_ok:
  3539                              <1> ; 17/04/2021
  3540                              <1> ; ('add_to_swap_queue' procedure call has been disabled as temporary)
  3541                              <1> ;
  3542                              <1> ;	; 20/07/2015
  3543                              <1> ;	mov	ebx, cr2
  3544                              <1> ;	call 	add_to_swap_queue
  3545                              <1> 	;
  3546                              <1> 	; The new PTE (which contains the new page) will be added to 
  3547                              <1> 	; the swap queue, here. 
  3548                              <1> 	; (Later, if memory will become insufficient, 
  3549                              <1> 	; one page will be swapped out which is at the head of 
  3550                              <1> 	; the swap queue by using FIFO and access check methods.)
  3551                              <1> 	;
  3552 000030FB 31C0                <1> 	xor	eax, eax  ; 0
  3553                              <1> 	;
  3554                              <1> pfh_err_retn:
  3555 000030FD 59                  <1> 	pop	ecx
  3556 000030FE 5A                  <1> 	pop	edx
  3557 000030FF 5B                  <1> 	pop	ebx
  3558 00003100 C3                  <1> 	retn 
  3559                              <1> 	
  3560                              <1> copy_page:
  3561                              <1> 	; 16/04/2021
  3562                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3563                              <1> 	; 22/09/2015
  3564                              <1> 	; 21/09/2015
  3565                              <1> 	; 19/09/2015
  3566                              <1> 	; 07/09/2015
  3567                              <1> 	; 31/08/2015
  3568                              <1> 	; 20/07/2015
  3569                              <1> 	; 05/05/2015
  3570                              <1> 	; 03/05/2015
  3571                              <1> 	; 18/04/2015
  3572                              <1> 	; 12/04/2015
  3573                              <1> 	; 30/10/2014
  3574                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3575                              <1> 	;
  3576                              <1> 	; INPUT -> 
  3577                              <1> 	;	EBX = Virtual (linear) address of source page
  3578                              <1> 	;	     (Page fault address)
  3579                              <1> 	; OUTPUT ->
  3580                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3581                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3582                              <1> 	;	EAX = 0 (CF = 1) 
  3583                              <1> 	;		if there is not a free page to be allocated
  3584                              <1> 	;	(page content of the source page will be copied
  3585                              <1> 	;	onto the target/new page) 	
  3586                              <1> 	;
  3587                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3588                              <1> 	;
  3589                              <1> 
  3590                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  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) ; 16/04/2021
  3603                              <1> 	
  3604 00003101 56                  <1> 	push	esi ; *
  3605 00003102 57                  <1> 	push	edi ; **
  3606                              <1> 	; 16/04/2021
  3607                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3608                              <1> 	;push	ebx ; ***
  3609                              <1> 	;push	ecx ; ****
  3610 00003103 31F6                <1> 	xor 	esi, esi
  3611 00003105 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3612 00003108 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3613 0000310A C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3614 0000310D 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3615 00003110 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3616 00003112 031D[08750000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3617 00003118 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3618 0000311A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3619 0000311E 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3620 00003120 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3621 00003126 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3622 0000312A 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3623                              <1> 	; 07/09/2015
  3624 0000312C 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3625                              <1> 				     ; read only page as a child process?)	
  3626 00003131 7509                <1> 	jnz	short cpp_0 ; yes
  3627 00003133 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3628 00003135 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3629 0000313A EB32                <1> 	jmp	short cpp_1
  3630                              <1> cpp_0:
  3631 0000313C 89FE                <1> 	mov	esi, edi
  3632 0000313E 0335[0C750000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3633 00003144 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3634 00003146 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3635 0000314A 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3636 0000314C 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3637 00003152 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3638 00003156 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3639 00003158 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3640                              <1> 	; 21/09/2015
  3641 0000315A 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3642 0000315C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3643                              <1> 	;
  3644 00003160 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3645 00003163 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3646                              <1> 	;
  3647 00003165 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3648 0000316A 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3649 0000316C 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3650                              <1> 			    ; Convert child's page to writable page
  3651                              <1> cpp_1:
  3652 0000316E E833FCFFFF          <1> 	call	allocate_page
  3653 00003173 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3654 00003175 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3655 00003177 7405                <1> 	jz	short cpp_2
  3656                              <1> 		; Convert read only page to writable page 
  3657                              <1> 		;(for the parent of the current process)
  3658                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3659                              <1> 	; 22/09/2015
  3660 00003179 890E                <1> 	mov	[esi], ecx
  3661 0000317B 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3662                              <1> 				 ; 1+2+4 = 7
  3663                              <1> cpp_2:
  3664 0000317E 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3665                              <1> 	; 07/09/2015
  3666 00003180 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3667 00003182 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3668 00003187 F3A5                <1> 	rep	movsd ; 31/08/2015
  3669                              <1> cpp_3:		
  3670 00003189 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3671 0000318B 8903                <1> 	mov	[ebx], eax ; Update PTE
  3672 0000318D 28C0                <1> 	sub	al, al ; clear attributes
  3673                              <1> cpp_4:
  3674                              <1> 	; 16/04/2021
  3675                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3676                              <1> 	;pop	ecx ; ****
  3677                              <1> 	;pop	ebx ; ***
  3678 0000318F 5F                  <1> 	pop	edi ; **
  3679 00003190 5E                  <1> 	pop	esi ; *
  3680 00003191 C3                  <1> 	retn
  3681                              <1> 
  3682                              <1> ;; 28/04/2015
  3683                              <1> ;; 24/10/2014
  3684                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3685                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3686                              <1> ;;
  3687                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3688                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3689                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3690                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3691                              <1> ;;
  3692                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3693                              <1> ;;
  3694                              <1> ;; Method:
  3695                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3696                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3697                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3698                              <1> ;;	When a new page is being allocated, swap queue is updated
  3699                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3700                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3701                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3702                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3703                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3704                              <1> ;;	offset value becomes it's previous offset value - 4.
  3705                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3706                              <1> ;;	the queue/list is not shifted.
  3707                              <1> ;;	After the queue/list shift, newly allocated page is added
  3708                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3709                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3710                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3711                              <1> ;;	
  3712                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3713                              <1> ;;	the first non-accessed, writable page in the list, 
  3714                              <1> ;;	from the head to the tail. The list is shifted to left 
  3715                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3716                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3717                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3718                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3719                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3720                              <1> ;;	procedure will be failed)...
  3721                              <1> ;;
  3722                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3723                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3724                              <1> ;;	(PTE) will be added to the tail of the queue after
  3725                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3726                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3727                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3728                              <1> ;;
  3729                              <1> ;;
  3730                              <1> ;;	
  3731                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3732                              <1> ;;
  3733                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3734                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3735                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3736                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3737                              <1> ;;
  3738                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3739                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3740                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3741                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3742                              <1> ;; 		 (entire swap space must be accessed by using
  3743                              <1> ;;		 31 bit offset address) 
  3744                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3745                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3746                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3747                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3748                              <1> ;;
  3749                              <1> ;; 					
  3750                              <1> ;; Method:
  3751                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3752                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3753                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3754                              <1> ;;	Swapping out is performed by using swap page queue.
  3755                              <1> ;;
  3756                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3757                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3758                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3759                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3760                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3761                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3762                              <1> ;;	calculated by adding offset value to the swap partition's 
  3763                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3764                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3765                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3766                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3767                              <1> ;;	is in a partitioned virtual hard disk.) 
  3768                              <1> ;;
  3769                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3770                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3771                              <1> ;;
  3772                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3773                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3774                              <1> ;;
  3775                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3776                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3777                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3778                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3779                              <1> ;;	it means relevant (respective) block is in use, and, 
  3780                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3781                              <1> ;;      swap disk/file block is free.
  3782                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3783                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3784                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3785                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3786                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3787                              <1> ;;	------------------------------------------------------------
  3788                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3789                              <1> ;;	------------------------------------------------------------
  3790                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3791                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3792                              <1> ;;
  3793                              <1> ;;	..............................................................
  3794                              <1> ;;
  3795                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3796                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3797                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3798                              <1> ;;	position with value of 1 on the table is converted to swap
  3799                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3800                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3801                              <1> ;;	number of physical swap disk or virtual swap disk)
  3802                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3803                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3804                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3805                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3806                              <1> ;;	If disk write procedure returns with error or free count of 
  3807                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3808                              <1> ;;	'insufficient memory error' (cf=1). 
  3809                              <1> ;;
  3810                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3811                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3812                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3813                              <1> ;;	free blocks after a disk write error. It will return to 
  3814                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3815                              <1> ;;
  3816                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3817                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3818                              <1> ;;	address (cf=0). 
  3819                              <1> ;;
  3820                              <1> ;;	..............................................................
  3821                              <1> ;;
  3822                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3823                              <1> ;;	file sectors at specified memory page. Then page allocation
  3824                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3825                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3826                              <1> ;;	to do, except to terminate the process which is the owner of
  3827                              <1> ;;	the swapped page.
  3828                              <1> ;;
  3829                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3830                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3831                              <1> ;;	updates [swpd_first] pointer if it is required.
  3832                              <1> ;;
  3833                              <1> ;;	..............................................................	 
  3834                              <1> ;;
  3835                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3836                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3837                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3838                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3839                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3840                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3841                              <1> ;;
  3842                              <1> 
  3843                              <1> ; 17/04/2021
  3844                              <1> ; ('swap_in' procedure call is disabled as temporary)
  3845                              <1> 
  3846                              <1> ; 30/11/2021 - temporary !
  3847                              <1> ;swap_in:
  3848                              <1> 	; 31/08/2015
  3849                              <1> 	; 20/07/2015
  3850                              <1> 	; 28/04/2015
  3851                              <1> 	; 18/04/2015
  3852                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3853                              <1> 	;
  3854                              <1> 	; INPUT -> 
  3855                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3856                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3857                              <1> 	;	EAX = Offset Address for the swapped page on the
  3858                              <1> 	;	      swap disk or in the swap file.
  3859                              <1> 	;
  3860                              <1> 	; OUTPUT ->
  3861                              <1> 	;	EAX = 0 if loading at memory has been successful
  3862                              <1> 	;
  3863                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3864                              <1> 	;		  or sector not present or drive not ready
  3865                              <1> 	;	     EAX = Error code
  3866                              <1> 	;	     [u.error] = EAX 
  3867                              <1> 	;		       = The last error code for the process
  3868                              <1> 	;		         (will be reset after returning to user)	  
  3869                              <1> 	;
  3870                              <1> 	; Modified Registers -> EAX
  3871                              <1> 	;
  3872                              <1> 
  3873                              <1> ;       cmp     dword [swp_drv], 0
  3874                              <1> ;	jna	short swpin_dnp_err
  3875                              <1> ;
  3876                              <1> ;	cmp	eax, [swpd_size]
  3877                              <1> ;	jnb	short swpin_snp_err
  3878                              <1> ;
  3879                              <1> ;	push	esi
  3880                              <1> ;	push	ebx
  3881                              <1> ;	push	ecx
  3882                              <1> ;	mov	esi, [swp_drv]	
  3883                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3884                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3885                              <1> ;		; size different than 512 bytes, logical disk sector
  3886                              <1> ;		; size is 512 bytes and disk reading procedure
  3887                              <1> ;		; will be performed for reading 4096 bytes
  3888                              <1> ;		; (2*2048, 8*512). 
  3889                              <1> ;	; ESI = Logical disk description table address
  3890                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3891                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3892                              <1> ;	; ECX = Sector count ; 8 sectors
  3893                              <1> ;	push	eax
  3894                              <1> ;	call	logical_disk_read
  3895                              <1> ;	pop	eax
  3896                              <1> ;	jnc	short swpin_read_ok
  3897                              <1> ;	;
  3898                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3899                              <1> ;	mov	[u.error], eax
  3900                              <1> ;	jmp	short swpin_retn
  3901                              <1> ;	;
  3902                              <1> ;swpin_read_ok:
  3903                              <1> ;	; EAX = Offset address (logical sector number)
  3904                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3905                              <1> ;	;
  3906                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3907                              <1> ;	; 20/07/2015
  3908                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3909                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3910                              <1> ;	mov	bl, [u.uno] ; current process number
  3911                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3912                              <1> ;	call	swap_queue_shift
  3913                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3914                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3915                              <1> ;	; zf = 1
  3916                              <1> ;swpin_retn:
  3917                              <1> ;	pop	ecx
  3918                              <1> ;	pop	ebx
  3919                              <1> ;	pop	esi
  3920                              <1> ;	retn
  3921                              <1> ;
  3922                              <1> ;swpin_dnp_err:
  3923                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3924                              <1> ;swpin_err_retn:
  3925                              <1> ;	mov	[u.error], eax
  3926                              <1> ;	stc
  3927                              <1> ;	retn
  3928                              <1> ;
  3929                              <1> ;swpin_snp_err:
  3930                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3931                              <1> ;	jmp	short swpin_err_retn
  3932                              <1> 
  3933                              <1> ; 17/04/2021
  3934                              <1> ; ('swap_out' procedure call is disabled as temporary)
  3935                              <1> 
  3936                              <1> ; 30/11/2021 - temporary !
  3937                              <1> ;swap_out:
  3938                              <1> 	; 10/06/2016
  3939                              <1> 	; 07/06/2016
  3940                              <1>         ; 23/05/2016
  3941                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3942                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3943                              <1> 	;
  3944                              <1> 	; INPUT -> 
  3945                              <1> 	;	none
  3946                              <1> 	;
  3947                              <1> 	; OUTPUT ->
  3948                              <1> 	;	EAX = Physical page address (which is swapped out
  3949                              <1> 	;	      for allocating a new page)
  3950                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3951                              <1> 	;		  or sector not present or drive not ready
  3952                              <1> 	;	     EAX = Error code
  3953                              <1> 	;	     [u.error] = EAX 
  3954                              <1> 	;		       = The last error code for the process
  3955                              <1> 	;		         (will be reset after returning to user)	  
  3956                              <1> 	;
  3957                              <1> 	; Modified Registers -> none (except EAX)
  3958                              <1> 	;
  3959                              <1> 
  3960                              <1> ;	cmp 	word [swpq_count], 1
  3961                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3962                              <1> ;
  3963                              <1> ;       ;cmp    dword [swp_drv], 1
  3964                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3965                              <1> ;
  3966                              <1> ;       cmp     dword [swpd_free], 1
  3967                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3968                              <1> ;
  3969                              <1> ;	push	ebx ; *
  3970                              <1> ;swpout_1:
  3971                              <1> ;	; 10/06/2016
  3972                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3973                              <1> ;	call	swap_queue_shift
  3974                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3975                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3976                              <1> ;				       ; pointer in the swap queue
  3977                              <1> ;	; EAX = PTE value of the page
  3978                              <1> ;	; EBX = PTE address of the page
  3979                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3980                              <1> ;	;
  3981                              <1> ;	; 07/06/2016
  3982                              <1> ;	; 19/05/2016
  3983                              <1> ;	; check this page is in timer events or not
  3984                              <1> ;	
  3985                              <1> ;swpout_timer_page_0:
  3986                              <1> ;	push	edx ; **
  3987                              <1> ;
  3988                              <1> ;	; 07/06/2016
  3989                              <1> ;	cmp	byte [timer_events], 0 
  3990                              <1> ;	jna	short swpout_2
  3991                              <1> ;	;
  3992                              <1> ;	mov	dl, [timer_events]
  3993                              <1> ;
  3994                              <1> ;	push	ecx ; ***
  3995                              <1> ;	push	ebx ; ****
  3996                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3997                              <1> ;			       ; structures 
  3998                              <1> ;swpout_timer_page_1:
  3999                              <1> ;	mov	cl, [ebx]
  4000                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4001                              <1> ;	jz	short swpout_timer_page_3
  4002                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4003                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4004                              <1> ;				; of the response byte address, to
  4005                              <1> ;				; get beginning of the page address)
  4006                              <1> ;	cmp	eax, ecx
  4007                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4008                              <1> ;	
  4009                              <1> ;	; !same page!
  4010                              <1> ;	;
  4011                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4012                              <1> ;	; This page will be used by the kernel to put timer event
  4013                              <1> ;	; response (signal return) byte at the requested address;
  4014                              <1> ;	; in order to prevent a possible wrong write (while
  4015                              <1> ;	; this page is swapped out) on physical memory,
  4016                              <1> ;	; we must protect this page against to be swapped out!
  4017                              <1> ;	;
  4018                              <1> ;	pop	ebx ; ****
  4019                              <1> ;	pop	ecx ; ***
  4020                              <1> ;	pop	edx ; **
  4021                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4022                              <1> ; 
  4023                              <1> ;swpout_timer_page_2:
  4024                              <1> ;	; 07/06/2016
  4025                              <1> ;	dec	dl
  4026                              <1> ;	jz	short swpout_timer_page_4
  4027                              <1> ;swpout_timer_page_3:
  4028                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4029                              <1> ;	;jnb	short swpout_timer_page_4
  4030                              <1> ;	add	ebx, 16
  4031                              <1> ;	jmp	short swpout_timer_page_1	
  4032                              <1> ;
  4033                              <1> ;swpout_timer_page_4:
  4034                              <1> ;	pop	ebx ; ****
  4035                              <1> ;	pop	ecx ; ***
  4036                              <1> ;swpout_2:
  4037                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4038                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4039                              <1> ;	;
  4040                              <1> ;	call	link_swap_block
  4041                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4042                              <1> ;				       ; because [swpd_free] value
  4043                              <1> ;				       ; was checked at the beginging. 	
  4044                              <1> ;	pop	edx ; **
  4045                              <1> ;	pop	ebx ; *
  4046                              <1> ;	jmp	short swpout_nfspc_err 
  4047                              <1> ;swpout_3:
  4048                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4049                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4050                              <1> ;	;	
  4051                              <1> ;	push	esi ; **
  4052                              <1> ;	push	ecx ; ***
  4053                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4054                              <1> ;	mov	esi, [swp_drv]	
  4055                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4056                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4057                              <1> ;		; size different than 512 bytes, logical disk sector
  4058                              <1> ;		; size is 512 bytes and disk writing procedure
  4059                              <1> ;		; will be performed for writing 4096 bytes
  4060                              <1> ;		; (2*2048, 8*512). 
  4061                              <1> ;	; ESI = Logical disk description table address
  4062                              <1> ;	; EBX = Buffer (Page) address
  4063                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4064                              <1> ;	; ECX = Sector count ; 8 sectors
  4065                              <1> ;	; edx = PTE address
  4066                              <1> ;	call	logical_disk_write
  4067                              <1> ;	; edx = PTE address
  4068                              <1> ;	pop	ecx ; sector address	
  4069                              <1> ;	jnc	short swpout_write_ok
  4070                              <1> ;	;
  4071                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4072                              <1> ;swpout_dw_err:
  4073                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4074                              <1> ;	mov	[u.error], eax
  4075                              <1> ;	jmp	short swpout_retn
  4076                              <1> ;	;
  4077                              <1> ;swpout_write_ok:
  4078                              <1> ;	; EBX = Buffer (page) address
  4079                              <1> ;	; EDX = Page Table Entry address
  4080                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4081                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4082                              <1> ;	mov 	[edx], ecx 
  4083                              <1> ;		; bit 0 = 0 (swapped page)
  4084                              <1> ;	mov	eax, ebx
  4085                              <1> ;swpout_retn:
  4086                              <1> ;	pop	ecx ; ***
  4087                              <1> ;	pop	esi ; **
  4088                              <1> ;	pop	ebx ; *
  4089                              <1> ;	retn
  4090                              <1> ;
  4091                              <1> ;;swpout_dnp_err:
  4092                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4093                              <1> ;;	jmp	short swpout_err_retn
  4094                              <1> ;swpout_nfspc_err:
  4095                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4096                              <1> ;swpout_err_retn:
  4097                              <1> ;	mov	[u.error], eax
  4098                              <1> ;	;stc
  4099                              <1> ;	retn
  4100                              <1> ;swpout_npts_err:
  4101                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4102                              <1> ;	pop	ebx
  4103                              <1> ;	jmp	short swpout_err_retn
  4104                              <1> ;swpout_im_err:
  4105                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4106                              <1> ;	jmp	short swpout_err_retn
  4107                              <1> 
  4108                              <1> ; 17/04/2021
  4109                              <1> ; ('swap_queue_shift' procedure call is disabled as temporary)
  4110                              <1> 
  4111                              <1> ; 30/11/2021 - temporary !
  4112                              <1> ;swap_queue_shift:
  4113                              <1> 	; 26/03/2017
  4114                              <1> 	; 10/06/2016
  4115                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4116                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4117                              <1> 	;
  4118                              <1> 	; INPUT ->
  4119                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4120                              <1> 	;	      and process number combination (bit 0 to 11)
  4121                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4122                              <1> 	;	
  4123                              <1> 	; OUTPUT ->
  4124                              <1> 	;	If EBX input > 0 
  4125                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4126                              <1> 	; 	   from the tail to the head, up to entry offset
  4127                              <1> 	; 	   which points to EBX input value or nothing
  4128                              <1> 	;	   to do if EBX value is not found on the queue.
  4129                              <1> 	;	   (The entry -with EBX value- will be removed
  4130                              <1> 	;	   from the queue if it is found.)
  4131                              <1> 	;
  4132                              <1> 	;	   EAX = 0		
  4133                              <1> 	;
  4134                              <1> 	;	If EBX input = 0
  4135                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4136                              <1> 	; 	   from the tail to the head, if the PTE address
  4137                              <1> 	;	   which is pointed in head of the queue is marked
  4138                              <1> 	;	   as "accessed" or it is marked as "non present".
  4139                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4140                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4141                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4142                              <1> 	;	   -without dropping pointer of the PTE from 
  4143                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4144                              <1> 	;	   Pointer in the head will be moved into the tail,
  4145                              <1> 	;	   other PTEs will be shifted on head direction.)
  4146                              <1> 	;
  4147                              <1> 	;	   Swap queue will be shifted up to the first
  4148                              <1> 	;	   'present' or 'non accessed' page will be found
  4149                              <1> 	;	   (as pointed) on the queue head (then it will be
  4150                              <1>         ;          removed/dropped from the queue).
  4151                              <1> 	;
  4152                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4153                              <1> 	;		 (it's pointer -virtual address-) dropped
  4154                              <1> 	;		 (removed) from swap queue.
  4155                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4156                              <1> 	;	         which is (it's pointer -virtual address-)
  4157                              <1> 	;		 dropped (removed) from swap queue.
  4158                              <1> 	;
  4159                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4160                              <1> 	;
  4161                              <1> 	; Modified Registers -> EAX, EBX
  4162                              <1> 	;
  4163                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4164                              <1> ;	and	ax, ax
  4165                              <1> ;	jz	short swpqs_retn
  4166                              <1> ;	push	edi
  4167                              <1> ;	push	esi
  4168                              <1> ;	push	ecx
  4169                              <1> ;	mov	esi, swap_queue
  4170                              <1> ;	mov	ecx, eax
  4171                              <1> ;	or	ebx, ebx
  4172                              <1> ;	jz	short swpqs_7
  4173                              <1> ;swpqs_1:
  4174                              <1> ;	lodsd
  4175                              <1> ;	cmp	eax, ebx
  4176                              <1> ;	je	short swpqs_2
  4177                              <1> ;	loop	swpqs_1
  4178                              <1> ;	; 10/06/2016
  4179                              <1> ;	sub	eax, eax 
  4180                              <1> ;	jmp	short swpqs_6
  4181                              <1> ;swpqs_2:
  4182                              <1> ;	mov	edi, esi
  4183                              <1> ;	sub 	edi, 4
  4184                              <1> ;swpqs_3:
  4185                              <1> ;	dec	word [swpq_count]
  4186                              <1> ;	jz	short swpqs_5
  4187                              <1> ;swpqs_4:
  4188                              <1> ;	dec 	ecx
  4189                              <1> ;	rep	movsd	; shift up (to the head)
  4190                              <1> ;swpqs_5:
  4191                              <1> ;	xor	eax, eax
  4192                              <1> ;	mov	[edi], eax
  4193                              <1> ;swpqs_6:
  4194                              <1> ;	pop	ecx
  4195                              <1> ;	pop	esi
  4196                              <1> ;	pop	edi
  4197                              <1> ;swpqs_retn:
  4198                              <1> ;	retn		
  4199                              <1> ;swpqs_7:
  4200                              <1> ;	mov	edi, esi ; head
  4201                              <1> ;	lodsd
  4202                              <1> ;	; 20/07/2015
  4203                              <1> ;	mov	ebx, eax
  4204                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4205                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4206                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4207                              <1> ;		      ; ax = process number (1 to 4095)
  4208                              <1> ;	cmp	al, [u.uno]
  4209                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4210                              <1> ;	jne	short swpqs_8
  4211                              <1> ;	mov	eax, [u.pgdir]
  4212                              <1> ;	jmp	short swpqs_9
  4213                              <1> ;swpqs_8:
  4214                              <1> ;	; 09/06/2016
  4215                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4216                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4217                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4218                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4219                              <1> ;
  4220                              <1> ;	;shl	ax, 2
  4221                              <1> ;	shl	al, 2
  4222                              <1> ;	mov 	eax, [eax+p.upage-4]
  4223                              <1> ;	or	eax, eax
  4224                              <1> ;	jz	short swpqs_3 ; invalid upage
  4225                              <1> ;	add	eax, u.pgdir - user
  4226                              <1> ;			 ; u.pgdir value for the process
  4227                              <1> ;			 ; is in [eax]
  4228                              <1> ;	mov	eax, [eax]
  4229                              <1> ;	and	eax, eax
  4230                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4231                              <1> ;swpqs_9:
  4232                              <1> ;	push	edx
  4233                              <1> ;	; eax = page directory
  4234                              <1> ;	; ebx = virtual address
  4235                              <1> ;	call	get_pte
  4236                              <1> ;	mov	ebx, edx	; PTE address
  4237                              <1> ;	pop	edx
  4238                              <1> ;	; 10/06/2016
  4239                              <1> ;	jc	short swpqs_13 ; empty PDE
  4240                              <1> ;	; EAX = PTE value
  4241                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4242                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4243                              <1> ;			        ; from the queue (head)
  4244                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4245                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4246                              <1> ;			        ; from the queue (head) 	
  4247                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4248                              <1> ;	;jnz	short swpqs_11  ; present
  4249                              <1> ;			        ; accessed page
  4250                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4251                              <1> ;	jc	short swpqs_11  ; accessed page
  4252                              <1> ;
  4253                              <1> ;	dec	ecx
  4254                              <1> ;	mov	[swpq_count], cx
  4255                              <1> ;       jz      short swpqs_10
  4256                              <1> ;		; esi = head + 4
  4257                              <1> ;		; edi = head
  4258                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4259                              <1> ;swpqs_10:
  4260                              <1> ;	mov	[edi], ecx ; 0
  4261                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4262                              <1> ;
  4263                              <1> ;swpqs_11:
  4264                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4265                              <1> ;	; Rotation (head -> tail)
  4266                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4267                              <1> ;	jz	short swpqs_10
  4268                              <1> ;		; esi = head + 4
  4269                              <1> ;		; edi = head
  4270                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4271                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4272                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4273                              <1> ;
  4274                              <1> ;	mov	cx, [swpq_count]
  4275                              <1> ;
  4276                              <1> ;swpqs_12:
  4277                              <1> ;	mov	esi, swap_queue ; head
  4278                              <1> ;       jmp     swpqs_7
  4279                              <1> ;
  4280                              <1> ;swpqs_13:
  4281                              <1> ;	dec	ecx
  4282                              <1> ;	mov	[swpq_count], cx
  4283                              <1> ;       jz      swpqs_5
  4284                              <1> ;	jmp	short swpqs_12
  4285                              <1> 
  4286                              <1> ; 17/04/2021
  4287                              <1> ; ('add_to_swp_queue' procedure call is disabled as temporary)
  4288                              <1> 
  4289                              <1> ; 30/11/2021 - temporary !
  4290                              <1> ;add_to_swap_queue:
  4291                              <1> 	; 20/02/2017
  4292                              <1> 	; 20/07/2015
  4293                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4294                              <1> 	;
  4295                              <1> 	; Adds new page to swap queue
  4296                              <1> 	; (page directories and page tables must not be added
  4297                              <1> 	; to swap queue)	
  4298                              <1> 	;
  4299                              <1> 	; INPUT ->
  4300                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4301                              <1> 	;	[u.uno]
  4302                              <1> 	;	20/02/2017
  4303                              <1> 	;	(Linear address = CORE + user's virtual address)
  4304                              <1> 	;
  4305                              <1> 	; OUTPUT ->
  4306                              <1> 	;	EAX = [swpq_count]
  4307                              <1> 	;	      (after the PTE has been added)
  4308                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4309                              <1> 	;	      the PTE could not be added.
  4310                              <1> 	;
  4311                              <1> 	; Modified Registers -> EAX
  4312                              <1> 	;
  4313                              <1> ;	push	ebx
  4314                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4315                              <1> ;	mov	bl, [u.uno] ; current process number
  4316                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4317                              <1> ;				 ; it is already on the queue
  4318                              <1> ;		; then add it to the tail of the queue
  4319                              <1> ;	movzx	eax, word [swpq_count]
  4320                              <1> ;	cmp	ax, 1024
  4321                              <1> ;	jb	short atsq_1
  4322                              <1> ;	sub	ax, ax
  4323                              <1> ;	pop	ebx
  4324                              <1> ;	retn
  4325                              <1> ;atsq_1:
  4326                              <1> ;	push	esi
  4327                              <1> ;	mov	esi, swap_queue
  4328                              <1> ;	and	ax, ax
  4329                              <1> ;	jz	short atsq_2
  4330                              <1> ;	shl	ax, 2	; convert to offset
  4331                              <1> ;	add	esi, eax
  4332                              <1> ;	shr	ax, 2
  4333                              <1> ;atsq_2:
  4334                              <1> ;	inc	ax
  4335                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4336                              <1> ;	mov	[swpq_count], ax
  4337                              <1> ;	pop	esi
  4338                              <1> ;	pop	ebx
  4339                              <1> ;	retn
  4340                              <1> 
  4341                              <1> ; 17/04/2021
  4342                              <1> ; ('unlink_swap_block' procedure call is disabled as temporary)
  4343                              <1> 
  4344                              <1> ; 30/11/2021 - temporary !
  4345                              <1> ;unlink_swap_block:
  4346                              <1> 	; 15/09/2015
  4347                              <1> 	; 30/04/2015
  4348                              <1> 	; 18/04/2015
  4349                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4350                              <1> 	;
  4351                              <1> 	; INPUT -> 
  4352                              <1> 	;	EAX = swap disk/file offset address
  4353                              <1> 	;	      (bit 1 to bit 31)
  4354                              <1> 	; OUTPUT ->
  4355                              <1> 	;	[swpd_free] is increased
  4356                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4357                              <1> 	;
  4358                              <1> 	; Modified Registers -> EAX
  4359                              <1> 	;
  4360                              <1> ;	push	ebx
  4361                              <1> ;	push	edx
  4362                              <1> ;	;
  4363                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4364                              <1> ;				     ; 3 bits right
  4365                              <1> ;				     ; to get swap block/page number
  4366                              <1> ;	mov	edx, eax
  4367                              <1> ;	; 15/09/2015
  4368                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4369                              <1> ;				     ; (1 allocation bit = 1 page)
  4370                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4371                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4372                              <1> ;				     ; (to get 32 bit position)			
  4373                              <1> ;	;
  4374                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4375                              <1> ;	add	ebx, edx
  4376                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4377                              <1> ;				     ; (allocation bit position)	 
  4378                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4379                              <1> ;				     ; than the address in 'swpd_next' ?
  4380                              <1> ;				     ; (next/first free block value)		
  4381                              <1> ;	jnb	short uswpbl_1	     ; no	
  4382                              <1> ;	mov	[swpd_next], eax     ; yes	
  4383                              <1> ;uswpbl_1:
  4384                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4385                              <1> ;				     ; set relevant bit to 1.
  4386                              <1> ;				     ; set CF to the previous bit value	
  4387                              <1> ;	cmc			     ; complement carry flag	
  4388                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4389                              <1> ;				     ; if the block is already deallocated
  4390                              <1> ;				     ; before.	
  4391                              <1> ;       inc     dword [swpd_free]
  4392                              <1> ;uswpbl_2:
  4393                              <1> ;	pop	edx
  4394                              <1> ;	pop	ebx
  4395                              <1> ;	retn
  4396                              <1> 
  4397                              <1> ; 17/04/2021
  4398                              <1> ; ('link_swap_block' procedure call is disabled as temporary)
  4399                              <1> 
  4400                              <1> ; 30/11/2021 - temporary !
  4401                              <1> ;link_swap_block:
  4402                              <1> 	; 01/07/2015
  4403                              <1> 	; 18/04/2015
  4404                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4405                              <1> 	;
  4406                              <1> 	; INPUT -> none
  4407                              <1> 	;
  4408                              <1> 	; OUTPUT ->
  4409                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4410                              <1> 	;	      in sectors (corresponding 
  4411                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4412                              <1> 	;
  4413                              <1> 	;	CF = 1 and EAX = 0 
  4414                              <1> 	; 		   if there is not a free block to be allocated	
  4415                              <1> 	;
  4416                              <1> 	; Modified Registers -> none (except EAX)
  4417                              <1> 	;
  4418                              <1> 
  4419                              <1> ;	;mov	eax, [swpd_free]
  4420                              <1> ;	;and	eax, eax
  4421                              <1> ;	;jz	short out_of_swpspc
  4422                              <1> ;	;
  4423                              <1> ;	push	ebx
  4424                              <1> ;	push	ecx
  4425                              <1> ;	;
  4426                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4427                              <1> ;	mov	ecx, ebx
  4428                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4429                              <1> ;				 ; next_free_swap_block >> 5
  4430                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4431                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4432                              <1> ;lswbl_scan:
  4433                              <1> ;	cmp	ebx, ecx
  4434                              <1> ;	ja	short lswbl_notfound
  4435                              <1> ;	;
  4436                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4437                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4438                              <1> ;			   ; loads the destination with an index to
  4439                              <1> ;			   ; first set bit. (0 -> 31) 
  4440                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4441                              <1> ;	; 01/07/2015
  4442                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4443                              <1> ;			 ;
  4444                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4445                              <1> ;			 ;	  with value of 1 means 
  4446                              <1> ;			 ;	  the corresponding page is free 
  4447                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4448                              <1> ;	add	ebx, 4
  4449                              <1> ;			 ; We return back for searching next page block
  4450                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4451                              <1> ;			 ;	 we always will find at least 1 free block here.
  4452                              <1> ;	jmp    	short lswbl_scan
  4453                              <1> ;	;
  4454                              <1> ;lswbl_notfound:	
  4455                              <1> ;	sub	ecx, swap_alloc_table
  4456                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4457                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4458                              <1> ;	xor	eax, eax
  4459                              <1> ;	mov	[swpd_free], eax
  4460                              <1> ;	stc
  4461                              <1> ;lswbl_ok:
  4462                              <1> ;	pop	ecx
  4463                              <1> ;	pop	ebx
  4464                              <1> ;	retn
  4465                              <1> ;	;
  4466                              <1> ;;out_of_swpspc:
  4467                              <1> ;;	stc
  4468                              <1> ;;	retn
  4469                              <1> ;
  4470                              <1> ;lswbl_found:
  4471                              <1> ;	mov	ecx, ebx
  4472                              <1> ;	sub	ecx, swap_alloc_table
  4473                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4474                              <1> ;				 ; address/offset (to the next)
  4475                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4476                              <1> ;	;
  4477                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4478                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4479                              <1> ;				 ; in the destination.
  4480                              <1> ;				 ;
  4481                              <1> ;				 ; Reset the bit which is corresponding to the 
  4482                              <1> ;				 ; (just) allocated block.
  4483                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4484                              <1> ;	add	eax, ecx	 ; = block number
  4485                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4486                              <1> ;				 ; 1 block =  8 sectors
  4487                              <1> ;	;
  4488                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4489                              <1> ;	;
  4490                              <1> ;	; NOTE: The relevant page table entry will be updated
  4491                              <1> ;	;       according to this EAX value...
  4492                              <1> ;	;
  4493                              <1> ;	jmp	short lswbl_ok
  4494                              <1> 
  4495                              <1> ; 17/04/2021
  4496                              <1> ; ('logical_disk_read' procedure call is disabled as temporary)
  4497                              <1> 
  4498                              <1> ; 30/11/2021 - temporary !
  4499                              <1> ;logical_disk_read:
  4500                              <1> 	; 20/07/2015
  4501                              <1> 	; 09/03/2015 (temporary code here)
  4502                              <1> 	;
  4503                              <1> 	; INPUT ->
  4504                              <1> 	; 	ESI = Logical disk description table address
  4505                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4506                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4507                              <1> 	; 	ECX = Sector count
  4508                              <1> 	;
  4509                              <1> 	;
  4510                              <1> ;	retn
  4511                              <1> 
  4512                              <1> ; 17/04/2021
  4513                              <1> ; ('logical_disk_write' procedure call is disabled as temporary)
  4514                              <1> 
  4515                              <1> ; 30/11/2021 - temporary !
  4516                              <1> ;logical_disk_write:
  4517                              <1> 	; 20/07/2015
  4518                              <1> 	; 09/03/2015 (temporary code here)
  4519                              <1> 	;
  4520                              <1> 	; INPUT ->
  4521                              <1> 	; 	ESI = Logical disk description table address
  4522                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4523                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4524                              <1> 	; 	ECX = Sector count
  4525                              <1> 	;
  4526                              <1> ;	retn
  4527                              <1> 
  4528                              <1> get_physical_addr:
  4529                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  4530                              <1> 	;	(temporary modifications)
  4531                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4532                              <1> 	; 18/10/2015
  4533                              <1> 	; 29/07/2015
  4534                              <1> 	; 20/07/2015
  4535                              <1> 	; 04/06/2015
  4536                              <1> 	; 20/05/2015
  4537                              <1> 	; 28/04/2015
  4538                              <1> 	; 18/04/2015
  4539                              <1> 	; Get physical address
  4540                              <1> 	;     (allocates a new page for user if it is not present)
  4541                              <1> 	;	
  4542                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4543                              <1> 	; (buffer) address to physical address (of the buffer).)
  4544                              <1> 	; ('sys write', 'sys read' system calls...)
  4545                              <1> 	;
  4546                              <1> 	; INPUT ->
  4547                              <1> 	;	EBX = virtual address
  4548                              <1> 	;	u.pgdir = page directory (physical) address
  4549                              <1> 	;
  4550                              <1> 	; OUTPUT ->
  4551                              <1> 	;	EAX = physical address 
  4552                              <1> 	;	EBX = linear address	
  4553                              <1> 	;	EDX = physical address of the page frame
  4554                              <1> 	;	      (with attribute bits)
  4555                              <1> 	;	ECX = byte count within the page frame
  4556                              <1> 	;
  4557                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4558                              <1> 	;
  4559                              <1> 
  4560                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4561 00003192 A1[08750000]        <1> 	mov	eax, [u.pgdir]
  4562                              <1> 
  4563                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4564                              <1> 	
  4565 00003197 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4566                              <1> 	;
  4567                              <1> 	;mov	eax, [u.pgdir]
  4568 0000319D E816FDFFFF          <1> 	call	get_pte
  4569                              <1> 		; EDX = Page table entry address (if CF=0)
  4570                              <1> 	        ;       Page directory entry address (if CF=1)
  4571                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4572                              <1> 		; EAX = Page table entry value (page address)
  4573                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4574 000031A2 731C                <1> 	jnc	short gpa_1
  4575                              <1> 	;
  4576 000031A4 E8FDFBFFFF          <1> 	call	allocate_page
  4577 000031A9 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4578                              <1> gpa_0:
  4579 000031AB E867FCFFFF          <1> 	call 	clear_page
  4580                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4581 000031B0 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4582                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4583                              <1> 			   ; (user, writable, present page)	
  4584 000031B2 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4585 000031B4 A1[08750000]        <1> 	mov	eax, [u.pgdir]	
  4586 000031B9 E8FAFCFFFF          <1> 	call	get_pte
  4587 000031BE 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4588                              <1> gpa_1:
  4589                              <1> 	; EAX = PTE value, EDX = PTE address
  4590 000031C0 A801                <1> 	test 	al, PTE_A_PRESENT
  4591 000031C2 750A                <1> 	jnz	short gpa_3
  4592 000031C4 09C0                <1> 	or	eax, eax
  4593 000031C6 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4594                              <1> 
  4595                              <1> ; 17/04/2021
  4596                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4597 000031C8 EB2C                <1> 	jmp	short gpa_im_err  ; temporary !
  4598                              <1> 
  4599                              <1> 	; 20/07/2015
  4600                              <1> ;	push	ebp
  4601                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4602                              <1> ;	; reload swapped page
  4603                              <1> ;	call	reload_page ; 28/04/2015
  4604                              <1> ;	pop	ebp
  4605                              <1> ;	jc	short gpa_retn
  4606                              <1> gpa_2:
  4607                              <1> ; 17/04/2021
  4608                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  4609                              <1> 
  4610                              <1> 	; 20/07/2015
  4611                              <1> 	; 20/05/2015
  4612                              <1> 	; add this page to swap queue
  4613                              <1> ;	push	eax 
  4614                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4615                              <1> ;	call 	add_to_swap_queue
  4616                              <1> ;	pop	eax
  4617                              <1> 		; PTE address in EDX
  4618                              <1> 		; virtual address in EBX
  4619                              <1> 
  4620                              <1> 	; EAX = memory page address
  4621 000031CA 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4622                              <1> 				  ; present flag, bit 0 = 1
  4623                              <1> 				  ; user flag, bit 2 = 1	
  4624                              <1> 				  ; writable flag, bit 1 = 1
  4625 000031CC 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4626                              <1> gpa_3:
  4627                              <1> 	; 18/10/2015
  4628 000031CE 89D9                <1> 	mov	ecx, ebx
  4629 000031D0 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4630 000031D6 89C2                <1> 	mov 	edx, eax
  4631 000031D8 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4632 000031DC 01C8                <1> 	add	eax, ecx
  4633 000031DE F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4634 000031E0 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4635 000031E6 F8                  <1> 	clc
  4636                              <1> gpa_retn:
  4637 000031E7 C3                  <1> 	retn	
  4638                              <1> gpa_4:	
  4639 000031E8 E8B9FBFFFF          <1> 	call	allocate_page
  4640 000031ED 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4641 000031EF E823FCFFFF          <1> 	call	clear_page
  4642 000031F4 EBD4                <1> 	jmp	short gpa_2
  4643                              <1> 
  4644                              <1> gpa_im_err:	
  4645 000031F6 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4646                              <1> 				  ; Major error = 0 (No protection fault)	
  4647 000031FB C3                  <1> 	retn
  4648                              <1> 
  4649                              <1> ; 17/04/2021
  4650                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4651                              <1> 
  4652                              <1> ; 30/11/2021 - temporary !
  4653                              <1> ;reload_page:
  4654                              <1> 	; 20/07/2015
  4655                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4656                              <1> 	;
  4657                              <1> 	; Reload (Restore) swapped page at memory
  4658                              <1> 	;
  4659                              <1> 	; INPUT -> 
  4660                              <1> 	;	EBP = Virtual (linear) memory address
  4661                              <1> 	;	EAX = PTE value (swap disk sector address)
  4662                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4663                              <1> 	; OUTPUT ->
  4664                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4665                              <1> 	;
  4666                              <1> 	;	CF = 1 and EAX = error code
  4667                              <1> 	;
  4668                              <1> 	; Modified Registers -> none (except EAX)
  4669                              <1> 	;
  4670                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4671                              <1> ;	push	ebx      ;
  4672                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4673                              <1> ;	call	allocate_page
  4674                              <1> ;	jc	short rlp_im_err
  4675                              <1> ;	xchg 	eax, ebx	
  4676                              <1> ;	; EBX = Physical memory (page) address
  4677                              <1> ;	; EAX = Swap disk (offset) address
  4678                              <1> ;	; EBP = Virtual (linear) memory address
  4679                              <1> ;	call	swap_in
  4680                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4681                              <1> ;	mov	eax, ebx	
  4682                              <1> ;rlp_retn:
  4683                              <1> ;	pop	ebx
  4684                              <1> ;	retn
  4685                              <1> ;	
  4686                              <1> ;rlp_im_err:	
  4687                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4688                              <1> ;				  ; Major error = 0 (No protection fault)	
  4689                              <1> ;	jmp	short rlp_retn
  4690                              <1> ;
  4691                              <1> ;rlp_swp_err:
  4692                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4693                              <1> ;	jmp	short rlp_retn
  4694                              <1> 
  4695                              <1> copy_page_dir:
  4696                              <1> 	; 17/04/2021 (temporary modifications)
  4697                              <1> 	; 19/09/2015
  4698                              <1> 	; temporary - 07/09/2015
  4699                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4700                              <1> 	;
  4701                              <1> 	; INPUT -> 
  4702                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4703                              <1> 	;		    page directory.
  4704                              <1> 	; OUTPUT ->
  4705                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4706                              <1> 	;	       page directory.
  4707                              <1> 	;	(New page directory with new page table entries.)
  4708                              <1> 	;	(New page tables with read only copies of the parent's
  4709                              <1> 	;	pages.)
  4710                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4711                              <1> 	;
  4712                              <1> 	; Modified Registers -> none (except EAX)
  4713                              <1> 	;
  4714 000031FC E8A5FBFFFF          <1> 	call	allocate_page
  4715 00003201 723E                <1> 	jc	short cpd_err
  4716                              <1> 	;
  4717 00003203 55                  <1> 	push	ebp ; 20/07/2015
  4718 00003204 56                  <1> 	push	esi
  4719 00003205 57                  <1> 	push	edi
  4720 00003206 53                  <1> 	push	ebx
  4721 00003207 51                  <1> 	push	ecx
  4722 00003208 8B35[08750000]      <1> 	mov	esi, [u.pgdir]
  4723 0000320E 89C7                <1> 	mov	edi, eax
  4724 00003210 50                  <1> 	push	eax ; save child's page directory address
  4725                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4726                              <1> 	; (use same system space for all user page tables) 
  4727 00003211 A5                  <1> 	movsd
  4728 00003212 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4729 00003217 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4730                              <1> cpd_0:	
  4731 0000321C AD                  <1> 	lodsd
  4732                              <1> 	;or	eax, eax
  4733                              <1>         ;jnz	short cpd_1
  4734 0000321D A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4735 0000321F 7508                <1> 	jnz	short cpd_1
  4736                              <1>  	; (virtual address at the end of the page table)	
  4737 00003221 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4738 00003227 EB0F                <1> 	jmp	short cpd_2
  4739                              <1> cpd_1:	
  4740 00003229 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4741 0000322D 89C3                <1> 	mov	ebx, eax
  4742                              <1> 	; EBX = Parent's page table address
  4743 0000322F E81F000000          <1> 	call	copy_page_table
  4744 00003234 720C                <1> 	jc	short cpd_p_err
  4745                              <1> 	; EAX = Child's page table address
  4746 00003236 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4747                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4748                              <1> 			 ; (present, writable, user)
  4749                              <1> cpd_2:
  4750 00003238 AB                  <1> 	stosd
  4751 00003239 E2E1                <1> 	loop	cpd_0
  4752                              <1> 	;
  4753 0000323B 58                  <1> 	pop	eax  ; restore child's page directory address
  4754                              <1> cpd_3:
  4755 0000323C 59                  <1> 	pop	ecx
  4756 0000323D 5B                  <1> 	pop	ebx
  4757 0000323E 5F                  <1> 	pop	edi
  4758 0000323F 5E                  <1> 	pop	esi
  4759 00003240 5D                  <1> 	pop	ebp
  4760                              <1> cpd_err:
  4761 00003241 C3                  <1> 	retn
  4762                              <1> cpd_p_err:
  4763                              <1> 	; release the allocated pages missing (recover free space)
  4764 00003242 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4765 00003243 8B1D[08750000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4766 00003249 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4767 0000324E 29C0                <1> 	sub	eax, eax ; 0
  4768 00003250 F9                  <1> 	stc
  4769 00003251 EBE9                <1> 	jmp	short cpd_3	
  4770                              <1> 
  4771                              <1> copy_page_table:
  4772                              <1> 	; 17/04/2021 (temporary modifications)
  4773                              <1> 	; 19/09/2015
  4774                              <1> 	; temporary - 07/09/2015
  4775                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4776                              <1> 	;
  4777                              <1> 	; INPUT -> 
  4778                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4779                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4780                              <1> 	; OUTPUT ->
  4781                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4782                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4783                              <1> 	;	CF = 1 -> error 
  4784                              <1> 	;
  4785                              <1> 	; Modified Registers -> EBP (except EAX)
  4786                              <1> 	;
  4787 00003253 E84EFBFFFF          <1> 	call	allocate_page
  4788 00003258 7244                <1> 	jc	short cpt_err
  4789                              <1> 	;
  4790 0000325A 50                  <1> 	push	eax ; *
  4791                              <1> 	;push 	ebx
  4792 0000325B 56                  <1> 	push	esi
  4793 0000325C 57                  <1> 	push	edi
  4794 0000325D 52                  <1> 	push	edx
  4795 0000325E 51                  <1> 	push	ecx
  4796                              <1> 	;
  4797 0000325F 89DE                <1> 	mov	esi, ebx
  4798 00003261 89C7                <1> 	mov	edi, eax
  4799 00003263 89C2                <1> 	mov	edx, eax
  4800 00003265 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4801                              <1> cpt_0:
  4802 0000326B AD                  <1> 	lodsd
  4803 0000326C A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4804                              <1> 	;jnz	short cpt_1 (*)
  4805                              <1> 	; 17/04/2021 (temporary (*)
  4806                              <1> 	;and	eax, eax (*)
  4807 0000326E 741E                <1> 	jz	short cpt_2  ; 17/04/2021
  4808                              <1> 	
  4809                              <1> ; 17/04/2021
  4810                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4811                              <1> ;
  4812                              <1> ;	; ebp = virtual (linear) address of the memory page
  4813                              <1> ;	call	reload_page ; 28/04/2015
  4814                              <1> ;	jc	short cpt_p_err
  4815                              <1> cpt_1:
  4816 00003270 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4817 00003274 89C1                <1> 	mov	ecx, eax
  4818                              <1> 	; Allocate a new page for the child process
  4819 00003276 E82BFBFFFF          <1> 	call	allocate_page
  4820 0000327B 721C                <1> 	jc	short cpt_p_err
  4821 0000327D 57                  <1> 	push	edi
  4822 0000327E 56                  <1> 	push	esi
  4823 0000327F 89CE                <1> 	mov	esi, ecx
  4824 00003281 89C7                <1> 	mov	edi, eax
  4825 00003283 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4826 00003288 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4827 0000328A 5E                  <1> 	pop	esi
  4828 0000328B 5F                  <1> 	pop	edi
  4829                              <1> 	; 
  4830                              <1> ; 17/04/2021
  4831                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)	
  4832                              <1> ;
  4833                              <1> ;	push	ebx
  4834                              <1> ;	push	eax
  4835                              <1> ;	mov	ebx, ebp
  4836                              <1> ;	; ebx = virtual address of the memory page
  4837                              <1> ;	call	add_to_swap_queue
  4838                              <1> ;	pop	eax
  4839                              <1> ;	pop	ebx
  4840                              <1> 	;
  4841                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4842 0000328C 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4843                              <1> cpt_2:
  4844 0000328E AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4845                              <1> 	;
  4846 0000328F 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4847                              <1> 	;
  4848 00003295 39D7                <1> 	cmp	edi, edx
  4849 00003297 72D2                <1> 	jb	short cpt_0
  4850                              <1> cpt_p_err:
  4851 00003299 59                  <1> 	pop	ecx
  4852 0000329A 5A                  <1> 	pop	edx
  4853 0000329B 5F                  <1> 	pop	edi
  4854 0000329C 5E                  <1> 	pop	esi
  4855                              <1> 	;pop	ebx
  4856 0000329D 58                  <1> 	pop	eax ; *
  4857                              <1> cpt_err:
  4858 0000329E C3                  <1> 	retn
  4859                              <1> 
  4860                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4861                              <1> 
  4862                              <1> ;; Data:
  4863                              <1> 
  4864                              <1> ; 09/03/2015
  4865                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4866                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4867                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  4868                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4869                              <1> ;swpd_next:  dd 0 ; next free page block
  4870                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2070                                  %include 'sysdefs.s' ; 09/03/2015
  2071                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2072                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2073                              <1> ; ****************************************************************************
  2074                              <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC
  2075                              <1> ; Last Modification: 08/02/2022
  2076                              <1> ;
  2077                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2078                              <1> ; (Modified from 
  2079                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2080                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2081                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2082                              <1> ; ----------------------------------------------------------------------------
  2083                              <1> ;
  2084                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2085                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2086                              <1> ; <Bell Laboratories (17/3/1972)>
  2087                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2088                              <1> ;
  2089                              <1> ; ****************************************************************************
  2090                              <1> 
  2091                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2092                              <1> ; (SB structure has been moved here from 'ux.s' 
  2093                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2094                              <1> ; (('ux.s' bss section addresses are being overlapped
  2095                              <1> ;    when SB structure is defined in 'ux.s'))
  2096                              <1> 
  2097                              <1> struc SB ; SuperBlock
  2098                              <1> 
  2099 00000000 ????????            <1> .Header:	resd 1
  2100                              <1> ;.HiddenSects:
  2101 00000004 ????????            <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2102                              <1> ;.TotalSects:
  2103 00000008 ????????            <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)
  2104 0000000C ????????            <1> .Version:	resd 1	
  2105 00000010 ????????            <1> .BlockSize:	resd 1	
  2106 00000014 ????????            <1> .InodeCount:	resd 1	
  2107 00000018 ????????            <1> .FreeMapAddr:	resd 1	
  2108 0000001C ????????            <1> .FreeMapSize:	resd 1	
  2109 00000020 ????????            <1> .InodeMapAddr:	resd 1	
  2110 00000024 ????????            <1> .InodeMapSize:	resd 1	
  2111 00000028 ????????            <1> .InodeTblAddr:	resd 1	
  2112 0000002C ????????            <1> .InodeTblSize:	resd 1	
  2113 00000030 ????????            <1> .FreeInodes:	resd 1	
  2114 00000034 ????????            <1> .FirstFreeIno:	resd 1	
  2115 00000038 ????????            <1> .FreeBlocks:	resd 1	
  2116 0000003C ????????            <1> .FirstFreeBlk:	resd 1	
  2117 00000040 <res 13h>           <1> .BootSecParms:	resb 19	; v1
  2118 00000053 ??????????          <1> .BSExtension:	resb 5	; v2 HDFS
  2119 00000058 ??                  <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2120 00000059 ??                  <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2121 0000005A ????                <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2122 0000005C ????????            <1> .ModifTime:	resd 1	; (last) modification time (*)
  2123 00000060 ????????            <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2124 00000064 ????????            <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2125 00000068 ??                  <1> .LBA_rw:	resb 1
  2126 00000069 ??                  <1> .ClusterSize:	resb 1
  2127 0000006A ??                  <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2128 0000006B ??                  <1> .Mounted:	resb 1
  2129 0000006C ????????            <1> .MountInode:	resd 1  ; double word
  2130 00000070 ??                  <1> .DevMajor:	resb 1
  2131 00000071 ??                  <1> .DevMinor:	resb 1
  2132 00000072 ??                  <1> .LongName:	resb 1
  2133 00000073 ??                  <1> .Direntry32:	resb 1
  2134                              <1> ; 18/07/2021
  2135 00000074 ????????            <1> .FileBuffer:	resd 1
  2136 00000078 ????????            <1> .ItabBuffer:	resd 1
  2137 0000007C ????????            <1> .ImapBuffer:	resd 1
  2138 00000080 ????????            <1> .FmapBuffer:	resd 1
  2139                              <1>  ; 15/07/2021
  2140 00000084 ????????            <1> .LastInode:	resd 1
  2141                              <1> ; 02/05/2021
  2142 00000088 ????????            <1> .FmapIndex:	resd 1
  2143 0000008C ????????            <1> .ImapIndex:	resd 1
  2144 00000090 ????????            <1> .ItableIndex:	resd 1
  2145 00000094 <res 168h>          <1> .Reserved:	resb 508-148 ; 18/07/2021
  2146 000001FC ????????            <1> .Footer:	resd 1
  2147                              <1> 
  2148                              <1> endstruc
  2149                              <1> 
  2150                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2151                              <1> ; (file structure has been moved here from 'ux.s' 
  2152                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2153                              <1> ; (('ux.s' bss section addresses are being overlapped
  2154                              <1> ;    when file structure is defined in 'ux.s'))
  2155                              <1> 
  2156                              <1> ; 22/11/2021
  2157                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision
  2158                              <1> 
  2159                              <1> struc file	; open files (fsp) structure
  2160 00000000 ????                <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  2161 00000002 ????                <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  2162 00000004 ??                  <1>   .drive:  resb 1  ; logical drive (disk) number
  2163 00000005 ??                  <1>   .flags:  resb 1  ; open mode and status
  2164 00000006 ??                  <1>   .count:  resb 1  ; number of processes that have file open
  2165                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  2166 00000007 ??                  <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  2167 00000008 ????????            <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  2168 0000000C ????????            <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  2169                              <1>  .size:  ; = 16		
  2170                              <1> endstruc 
  2171                              <1> 
  2172                              <1> nproc 	equ	16  ; number of processes
  2173                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2174                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2175                              <1> nfiles  equ	50  ; NFILES equ 50 ; 02/01/2022
  2176                              <1> 
  2177                              <1> ; 27/12/2021
  2178                              <1> ;NFILES	  equ   32  ; temporary ! ( 27/12/2021)
  2179                              <1> ; 02/01/2022
  2180                              <1> ;OPENFILES equ	10  ; open files (for user) ; 28/03/2020
  2181                              <1> 
  2182                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2183                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2184                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2185                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2186                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2187                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2188                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2189                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2190                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2191                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2192                              <1> 	; '/core' dump file size = 32768 bytes
  2193                              <1>  
  2194                              <1> ; 08/03/2014 
  2195                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)
  2196                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2197                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2198                              <1> 
  2199                              <1> ; 30/08/2013
  2200                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2201                              <1> 
  2202                              <1> ; 05/02/2014
  2203                              <1> ; process status
  2204                              <1> ;SFREE 	equ 0
  2205                              <1> ;SRUN	equ 1
  2206                              <1> ;SWAIT	equ 2
  2207                              <1> ;SZOMB	equ 3
  2208                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2209                              <1> 
  2210                              <1> ; 09/03/2015
  2211                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2212                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2213                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2214                              <1> 
  2215                              <1> ; 17/09/2015
  2216                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2217                              <1> 
  2218                              <1> ; 12/01/2022 (37,38,39)
  2219                              <1> ; 21/09/2015 (36) 
  2220                              <1> ; 01/07/2015 (35)
  2221                              <1> ; 14/07/2013 (0-34)
  2222                              <1> ; UNIX v1 system calls
  2223                              <1> _rele 	equ 0
  2224                              <1> _exit 	equ 1
  2225                              <1> _fork 	equ 2
  2226                              <1> _read 	equ 3
  2227                              <1> _write	equ 4
  2228                              <1> _open	equ 5
  2229                              <1> _close 	equ 6
  2230                              <1> _wait 	equ 7
  2231                              <1> _creat 	equ 8
  2232                              <1> _link 	equ 9
  2233                              <1> _unlink	equ 10
  2234                              <1> _exec	equ 11
  2235                              <1> _chdir	equ 12
  2236                              <1> _time 	equ 13
  2237                              <1> _mkdir 	equ 14
  2238                              <1> _chmod	equ 15
  2239                              <1> _chown	equ 16
  2240                              <1> _break	equ 17
  2241                              <1> _stat	equ 18
  2242                              <1> _seek	equ 19
  2243                              <1> _tell 	equ 20
  2244                              <1> _mount	equ 21
  2245                              <1> _umount	equ 22
  2246                              <1> _setuid	equ 23
  2247                              <1> _getuid	equ 24
  2248                              <1> _stime	equ 25
  2249                              <1> _quit	equ 26	
  2250                              <1> _intr	equ 27
  2251                              <1> _fstat	equ 28
  2252                              <1> _emt 	equ 29
  2253                              <1> _mdate 	equ 30
  2254                              <1> _stty 	equ 31
  2255                              <1> _gtty	equ 32
  2256                              <1> _ilgins	equ 33
  2257                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2258                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2259                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2260                              <1> ; 12/01/2022 - Retro UNIX 386 v1.2
  2261                              <1> ; Retro UNIX 386 v2 system calls
  2262                              <1> _setgid	equ 37
  2263                              <1> _getgid	equ 38
  2264                              <1> _sysver	equ 39 ; (get) Retro Unix 386 version
  2265                              <1> 
  2266                              <1> %macro sys 1-4
  2267                              <1>     ; 13/04/2015
  2268                              <1>     ; Retro UNIX 386 v1 system call.
  2269                              <1>     mov eax, %1
  2270                              <1>     %if %0 >= 2   
  2271                              <1>         mov ebx, %2
  2272                              <1>         %if %0 >= 3    
  2273                              <1>             mov ecx, %3
  2274                              <1>             %if %0 = 4
  2275                              <1>                mov edx, %4   
  2276                              <1>             %endif
  2277                              <1>         %endif
  2278                              <1>     %endif
  2279                              <1>     int 30h	   
  2280                              <1> %endmacro
  2281                              <1> 
  2282                              <1> ; 13/05/2015 - ERROR CODES
  2283                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2284                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2285                              <1> ; 14/05/2015
  2286                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2287                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2288                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2289                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error
  2290                              <1> ; 16/05/2015		
  2291                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2292                              <1> ; 18/05/2015
  2293                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2294                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2295                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2296                              <1> ; 07/06/2015
  2297                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2298                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2299                              <1> ; 09/06/2015
  2300                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2301                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2302                              <1> ; 16/06/2015
  2303                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2304                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2305                              <1> ; 22/06/2015
  2306                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2307                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2308                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2309                              <1> ; 23/06/2015
  2310                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2311                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2312                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2313                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2314                              <1> ; 27/06/2015
  2315                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2316                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2317                              <1> ; 29/06/2015
  2318                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error
  2319                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2320                              <1> ; 08/02/2022 
  2321                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2322                              <1> ; 10/10/2016
  2323                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2324                              <1> ; 18/05/2016
  2325                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2326                              <1> ; 15/10/2016
  2327                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2328                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2329                              <1> ; 16/10/2016
  2330                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2331                              <1> ; 08/02/2022
  2332                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2333                              <1> 
  2334                              <1> ; 26/08/2015
  2335                              <1> ; 24/07/2015
  2336                              <1> ; 24/06/2015
  2337                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2338                              <1> ; 01/07/2015
  2339                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2340                              <1> ;
  2341                              <1> ; 26/11/2021 ('no free blocks on disk !' error)
  2342                              <1> ERR_ALLOC	   equ 33  ; 'disk allocation error !'	
  2343                              <1> ; 22/11/2021
  2344                              <1> ERR_READ_ONLY_FS   equ 30  ; 'read only file system !' error
  2345                              <1> ; 28/11/2021
  2346                              <1> ERR_INV_FILE	   equ 255 ; 'invalid file (inode) !' error
  2347                              <1> ; 04/12/2021
  2348                              <1> ERR_PERM_DENIED	   equ 11  ; 'permission denied !' error
  2349                              <1> ; 11/12/2021
  2350                              <1> ERR_INV_FUNC	   equ 1   ; 'invalid system call !' error
  2351                              <1> ; 10/01/2022
  2352                              <1> ERR_INO_ALLOC	   equ 33  ; 'inode allocation error !'
  2353                              <1> ERR_NOT_REGULAR    equ 255 ; 'not regular file directory !' error
  2354                              <1> 
  2355                              <1> ; 12/01/2022 - Retro UNIX 386 v1.2
  2356                              <1> %define s.time systm+504 ; boot/sysinit time (or current time)
  2357                              <1> 		
  2071                                  %include 'u0.s'      ; 15/03/2015
  2072                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2073                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2074                              <1> ; ****************************************************************************
  2075                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS0.INC
  2076                              <1> ; Last Modification: 06/02/2022
  2077                              <1> ; ----------------------------------------------------------------------------
  2078                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2079                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2080                              <1> ;
  2081                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2082                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2083                              <1> ; <Bell Laboratories (17/3/1972)>
  2084                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2085                              <1> ;
  2086                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2087                              <1> ;
  2088                              <1> ; ****************************************************************************
  2089                              <1> 
  2090                              <1> sys_init:
  2091                              <1> 	; 08/01/2022
  2092                              <1> 	; 01/01/2022
  2093                              <1> 	; 26/12/2021
  2094                              <1> 	; 27/11/2021
  2095                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 (test) compatibility modification
  2096                              <1> 	; 18/10/2015
  2097                              <1> 	; 28/08/2015
  2098                              <1> 	; 24/08/2015
  2099                              <1> 	; 14/08/2015
  2100                              <1> 	; 24/07/2015 
  2101                              <1> 	; 02/07/2015
  2102                              <1> 	; 01/07/2015
  2103                              <1> 	; 23/06/2015
  2104                              <1> 	; 15/04/2015
  2105                              <1> 	; 13/04/2015
  2106                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2107                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2108                              <1> 	;
  2109                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2110                              <1> 	;
  2111                              <1> 	;; 14/02/2014
  2112                              <1> 	;; 14/07/2013
  2113                              <1> 	;mov	ax, 41
  2114                              <1> 	;mov	[rootdir], ax
  2115                              <1> 	;mov	[u.cdir], ax
  2116                              <1> 	;and	al, 1 ; 15/04/2015
  2117                              <1> 	
  2118                              <1> 	; 27/11/2021
  2119                              <1> 	; 18/04/2021 - Retro UNIX 386 v2
  2120 0000329F 31C0                <1> 	xor	eax, eax
  2121 000032A1 FEC0                <1> 	inc	al	; eax = 1 (root directory inode) ; runix v2 fs
  2122 000032A3 A3[90740000]        <1> 	mov	[rootdir], eax ; = 1 ; 28/10/2021 (32 bit)
  2123 000032A8 A3[AC740000]        <1> 	mov	[u.cdir], eax ; 28/10/2021 (32 bit)
  2124                              <1> 
  2125 000032AD A2[F9740000]        <1> 	mov	[u.uno], al ; = 1
  2126                              <1> 	;mov	[mpid], ax ; 1 
  2127                              <1> 	;mov	[p.pid], ax ; 1
  2128                              <1> 	; 01/01/2022
  2129 000032B2 A2[8E740000]        <1> 	mov	[mpid], al
  2130 000032B7 A2[84700000]        <1> 	mov	[p.pid], al
  2131 000032BC A2[F4700000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2132                              <1> 	;
  2133 000032C1 B004                <1> 	mov	al, time_count ; 30/08/2013
  2134 000032C3 A2[F0740000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2135                              <1> 	; 02/07/2015
  2136 000032C8 A1[886F0000]        <1> 	mov	eax, [k_page_dir]
  2137 000032CD A3[08750000]        <1> 	mov	[u.pgdir], eax ; reset
  2138                              <1> 	; 18/10/2015
  2139                              <1> 	;sub	eax, eax
  2140                              <1> 	;mov	[u.ppgdir], eax ; 0
  2141                              <1>         ;
  2142 000032D2 E82E030000          <1>  	call	epoch
  2143 000032D7 A3[4C770000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2144                              <1> 	; 17/07/2013
  2145 000032DC E885060000          <1> 	call 	bf_init ; buffer initialization 
  2146                              <1> 	; 23/06/2015
  2147 000032E1 E8C0FAFFFF          <1> 	call	allocate_page
  2148                              <1> 	;;jc	error
  2149                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2150                              <1> 	; 05/12/2021
  2151 000032E6 7305                <1> 	jnc	short sysinit_1
  2152 000032E8 E989000000          <1> 	jmp	panic
  2153                              <1> sysinit_1:
  2154 000032ED A3[04750000]        <1> 	mov	[u.upage], eax ; user structure page	
  2155 000032F2 A3[04710000]        <1> 	mov	[p.upage], eax
  2156                              <1> 	;
  2157 000032F7 E81BFBFFFF          <1> 	call	clear_page
  2158                              <1> 	;
  2159                              <1> 	; 14/08/2015
  2160 000032FC FA                  <1> 	cli
  2161                              <1> 	; 14/03/2015
  2162                              <1> 	; 17/01/2014
  2163 000032FD E8D0010000          <1> 	call	sp_init ; serial port initialization
  2164                              <1> 	; 14/08/2015
  2165 00003302 FB                  <1> 	sti
  2166                              <1> 	;
  2167                              <1> 	; 30/06/2015
  2168                              <1> 	;mov	esi, kernel_init_ok_msg
  2169                              <1> 	;call 	print_msg
  2170                              <1> 	;
  2171 00003303 30DB                <1> 	xor	bl, bl ; video page 0
  2172                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2173 00003305 E8AF320000          <1> 	call 	vp_clr  ; 17/07/2013
  2174 0000330A FEC3                <1> 	inc	bl
  2175 0000330C 80FB08              <1> 	cmp	bl, 8
  2176 0000330F 72F4                <1> 	jb	short vp_clr_nxt
  2177                              <1> 	;
  2178                              <1> 	; 24/07/2015
  2179                              <1> 	;push	KDATA
  2180                              <1>         ;push	esp
  2181                              <1> 	;mov	[tss.esp0], esp
  2182                              <1>         ;mov	word [tss.ss0], KDATA
  2183                              <1> 	;
  2184                              <1> 	; 08/01/2022
  2185                              <1> 	; 24/08/2015
  2186                              <1> 	;; temporary (01/07/2015)
  2187                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2188                              <1> 	;		       ; it is not needed here !
  2189                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2190 00003311 FE0D[9E740000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2191                              <1> 			      ; 0 = executing a system call
  2192                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2193                              <1> 	;
  2194                              <1> 	;;; 06/08/2015
  2195                              <1> 	;;;call	getch ; wait for a key stroke
  2196                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2197                              <1> ;;sys_init_msg_wait:
  2198                              <1> ;;	push 	ecx
  2199                              <1> ;;	mov	al, 1
  2200                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2201                              <1> ;;	call	getc_n
  2202                              <1> ;;	pop	ecx
  2203                              <1> ;;	jnz	short sys_init_msg_ok
  2204                              <1> ;;	loop	sys_init_msg_wait
  2205                              <1> 	;
  2206                              <1> ;;sys_init_msg_ok:
  2207                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2208 00003317 6A10                <1> 	push	KDATA ; ss
  2209 00003319 54                  <1> 	push	esp
  2210 0000331A 9C                  <1> 	pushfd
  2211 0000331B 6A08                <1> 	push	KCODE ; cs
  2212 0000331D 68[4A330000]        <1> 	push	init_exec ; eip
  2213 00003322 8925[A0740000]      <1> 	mov	[u.sp], esp
  2214 00003328 1E                  <1> 	push	ds
  2215 00003329 06                  <1> 	push	es
  2216 0000332A 0FA0                <1> 	push	fs
  2217 0000332C 0FA8                <1> 	push	gs	
  2218 0000332E 60                  <1> 	pushad
  2219 0000332F 8925[A4740000]      <1> 	mov	[u.usp], esp
  2220 00003335 E8BA1B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2221                              <1> 		      ; and interrupt return components (for IRET)
  2222 0000333A 61                  <1> 	popad
  2223 0000333B 6658                <1> 	pop	ax ; gs
  2224 0000333D 6658                <1> 	pop	ax ; fs
  2225 0000333F 6658                <1> 	pop	ax ; es
  2226 00003341 6658                <1> 	pop	ax ; ds	
  2227 00003343 58                  <1> 	pop	eax ; eip (init_exec)
  2228 00003344 6658                <1> 	pop	ax ; cs (KCODE)
  2229 00003346 58                  <1> 	pop	eax ; E-FLAGS
  2230 00003347 58                  <1> 	pop	eax ; esp
  2231 00003348 6658                <1> 	pop	ax ; ss (KDATA)
  2232                              <1> 	;
  2233                              <1> 	; 26/12/2021 ([u.ppgdir] is zero already)
  2234                              <1> 	;xor	eax, eax ; 0
  2235                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2236                              <1> 	;
  2237                              <1> 	; 02/07/2015
  2238                              <1> 	; [u.pgdir ] = [k_page_dir]
  2239                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2240                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2241                              <1> init_exec:
  2242                              <1> 	; 13/03/2013
  2243                              <1> 	; 24/07/2013
  2244 0000334A BB[6C330000]        <1> 	mov	ebx, init_file
  2245 0000334F B9[64330000]        <1> 	mov	ecx, init_argp
  2246                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2247                              <1> 	; ECX contains address of argument list pointer
  2248                              <1> 	;
  2249                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2250                              <1> 			      ; 0 = executing a system call
  2251                              <1> 	sys	_exec  ; execute file
  2267                              <2> 
  2268                              <2> 
  2269 00003354 B80B000000          <2>  mov eax, %1
  2270                              <2>  %if %0 >= 2
  2271                              <2>  mov ebx, %2
  2272                              <2>  %if %0 >= 3
  2273                              <2>  mov ecx, %3
  2274                              <2>  %if %0 = 4
  2275                              <2>  mov edx, %4
  2276                              <2>  %endif
  2277                              <2>  %endif
  2278                              <2>  %endif
  2279 00003359 CD30                <2>  int 30h
  2252 0000335B 7319                <1> 	jnc	short panic
  2253                              <1> 	;
  2254 0000335D BE[9C6C0000]        <1> 	mov	esi, etc_init_err_msg
  2255                              <1> 	; 22/11/2021
  2256                              <1> 	;call 	print_msg
  2257 00003362 EB17                <1> 	jmp	short key_to_reboot
  2258                              <1> 
  2259                              <1> ;align 4
  2260                              <1> init_argp:
  2261 00003364 [6C330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2262                              <1> init_file:
  2263                              <1> 	; 24/08/2015
  2264 0000336C 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2264 00003375 00                  <1>
  2265                              <1> panic:
  2266                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2267                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2268 00003376 BE[816C0000]        <1> 	mov 	esi, panic_msg
  2269                              <1> key_to_reboot: ; 22/11/2021
  2270 0000337B E819000000          <1> 	call 	print_msg
  2271                              <1> ;key_to_reboot:
  2272                              <1> 	; 15/11/2015
  2273 00003380 E882300000          <1> 	call 	getch 
  2274                              <1> 		; wait for a character from the current tty
  2275                              <1> 	;
  2276 00003385 B00A                <1> 	mov	al, 0Ah
  2277 00003387 8A1D[B66F0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2278 0000338D B407                <1> 	mov	ah, 07h ; Black background, 
  2279                              <1> 			; light gray forecolor
  2280 0000338F E826E0FFFF          <1> 	call 	write_tty
  2281 00003394 E9C1DCFFFF          <1> 	jmp	cpu_reset 
  2282                              <1> 
  2283                              <1> print_msg:
  2284                              <1> 	; 01/07/2015
  2285                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2286                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2287                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2288                              <1> 	;
  2289                              <1> 	;
  2290 00003399 AC                  <1> 	lodsb
  2291                              <1> pmsg1:
  2292 0000339A 56                  <1> 	push 	esi
  2293 0000339B 0FB61D[B66F0000]    <1> 	movzx	ebx, byte [ptty]
  2294 000033A2 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2295 000033A4 E811E0FFFF          <1> 	call 	write_tty
  2296 000033A9 5E                  <1> 	pop	esi
  2297 000033AA AC                  <1> 	lodsb
  2298 000033AB 20C0                <1> 	and 	al, al
  2299 000033AD 75EB                <1> 	jnz 	short pmsg1
  2300 000033AF C3                  <1> 	retn
  2301                              <1> 	
  2302                              <1> ctrlbrk:
  2303                              <1> 	; 06/02/2022
  2304                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2305                              <1> 	; 12/11/2015
  2306                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2307                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2308                              <1> 	;
  2309                              <1> 	; INT 1Bh (control+break) handler		
  2310                              <1> 	;
  2311                              <1>       	; Retro Unix 8086 v1 feature only!
  2312                              <1>       	;
  2313 000033B0 66833D[F4740000]00  <1> 	cmp 	word [u.intr], 0
  2314 000033B8 764B                <1> 	jna 	short cbrk4
  2315                              <1> cbrk0:
  2316                              <1> 	; 12/11/2015
  2317                              <1> 	; 06/12/2013
  2318 000033BA 66833D[F6740000]00  <1> 	cmp 	word [u.quit], 0
  2319 000033C2 7441                <1> 	jz	short cbrk4
  2320                              <1> 	;
  2321                              <1> 	; 20/09/2013	
  2322                              <1> 	;push 	ax
  2323                              <1> 	; 04/12/2021
  2324 000033C4 50                  <1> 	push	eax
  2325                              <1> 
  2326                              <1> 	; 06/02/2022
  2327                              <1> 	; (repetitive ctrl+brk check) 
  2328 000033C5 66A1[F6740000]      <1> 	mov	ax, [u.quit]
  2329 000033CB 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2330 000033CD 7435                <1> 	jz	short cbrk3
  2331                              <1> 
  2332                              <1> 	; 06/12/2013
  2333 000033CF A0[B66F0000]        <1> 	mov	al, [ptty]
  2334                              <1> 	;
  2335                              <1> 	; 12/11/2015
  2336                              <1> 	;
  2337                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2338                              <1> 	; or ctrl+break from console (pseudo) tty
  2339                              <1> 	; (!redirection!)
  2340                              <1> 	;
  2341 000033D4 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2342 000033D6 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2343                              <1> 	;	
  2344                              <1> 	; Serial port interrupt handler sets [ptty]
  2345                              <1> 	; to the port's tty number (as temporary).
  2346                              <1> 	;
  2347                              <1> 	; If active process is using a stdin or 
  2348                              <1> 	; stdout redirection (by the shell),
  2349                              <1>         ; console tty keyboard must be available
  2350                              <1> 	; to terminate running process,
  2351                              <1> 	; in order to prevent a deadlock. 
  2352                              <1> 	;
  2353 000033D8 52                  <1> 	push	edx
  2354 000033D9 0FB615[F9740000]    <1> 	movzx	edx, byte [u.uno]
  2355 000033E0 3A82[C3700000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2356 000033E6 5A                  <1> 	pop	edx
  2357 000033E7 7412                <1> 	je	short cbrk2
  2358                              <1> cbrk1:
  2359 000033E9 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2360                              <1> 	; 06/12/2013
  2361 000033EB 3A05[DE740000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2362 000033F1 7408                <1> 	je	short cbrk2	
  2363 000033F3 3A05[DF740000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2364 000033F9 7509                <1> 	jne	short cbrk3	
  2365                              <1> cbrk2:
  2366                              <1> 	;; 06/12/2013
  2367                              <1> 	;mov	ax, [u.quit]
  2368                              <1> 	;and	ax, ax
  2369                              <1> 	;jz	short cbrk3
  2370                              <1> 	;
  2371                              <1> 	;xor	ax, ax ; 0
  2372                              <1> 	;dec	ax
  2373                              <1> 	; 04/12/2021
  2374 000033FB 31C0                <1> 	xor	eax, eax ; 0
  2375 000033FD 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2376                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2377 000033FE 66A3[F6740000]      <1> 	mov	[u.quit], ax
  2378                              <1> cbrk3:
  2379                              <1> 	;pop	ax
  2380                              <1> 	; 04/12/2021
  2381 00003404 58                  <1> 	pop	eax
  2382                              <1> cbrk4:
  2383 00003405 C3                  <1> 	retn
  2384                              <1> 
  2385                              <1> com2_int:
  2386                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2387                              <1> 	; 07/11/2015 
  2388                              <1> 	; 24/10/2015
  2389                              <1> 	; 23/10/2015
  2390                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2391                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2392                              <1> 	; < serial port 2 interrupt handler >
  2393                              <1> 	;
  2394 00003406 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2395                              <1> 	;;push	eax
  2396                              <1> 	; 08/01/2022
  2397 00003409 29C0                <1> 	sub	eax, eax
  2398 0000340B B009                <1> 	mov	al, 9
  2399                              <1> 	;mov	ax, 9
  2400 0000340D EB07                <1> 	jmp	short comm_int
  2401                              <1> com1_int:
  2402                              <1> 	; 07/11/2015
  2403                              <1> 	; 24/10/2015
  2404 0000340F 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2405                              <1> 	; 23/10/2015
  2406                              <1> 	;push	eax
  2407                              <1> 	; 08/01/2022
  2408 00003412 29C0                <1> 	sub	eax, eax
  2409 00003414 B008                <1> 	mov	al, 8
  2410                              <1> 	;mov	ax, 8
  2411                              <1> comm_int:
  2412                              <1> 	; 08/01/2022
  2413                              <1> 	; 20/11/2015
  2414                              <1> 	; 18/11/2015
  2415                              <1> 	; 17/11/2015
  2416                              <1> 	; 16/11/2015
  2417                              <1> 	; 09/11/2015
  2418                              <1> 	; 08/11/2015
  2419                              <1> 	; 07/11/2015
  2420                              <1> 	; 06/11/2015 (serial4.asm, 'serial')	
  2421                              <1> 	; 01/11/2015
  2422                              <1> 	; 26/10/2015
  2423                              <1> 	; 23/10/2015
  2424 00003416 53                  <1> 	push	ebx
  2425 00003417 56                  <1> 	push	esi
  2426 00003418 57                  <1> 	push	edi
  2427 00003419 1E                  <1> 	push 	ds
  2428 0000341A 06                  <1> 	push 	es
  2429                              <1> 	; 18/11/2015
  2430 0000341B 0F20DB              <1> 	mov	ebx, cr3
  2431 0000341E 53                  <1> 	push	ebx ; ****
  2432                              <1> 	;
  2433 0000341F 51                  <1> 	push	ecx ; ***
  2434 00003420 52                  <1> 	push	edx ; **
  2435                              <1> 	;
  2436 00003421 BB10000000          <1> 	mov	ebx, KDATA
  2437 00003426 8EDB                <1> 	mov	ds, bx
  2438 00003428 8EC3                <1> 	mov	es, bx
  2439                              <1> 	;
  2440 0000342A 8B0D[886F0000]      <1> 	mov	ecx, [k_page_dir]
  2441 00003430 0F22D9              <1> 	mov	cr3, ecx
  2442                              <1> 	; 20/11/2015
  2443                              <1> 	; Interrupt identification register
  2444 00003433 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2445                              <1> 	;
  2446 00003437 3C08                <1> 	cmp 	al, 8 
  2447 00003439 7702                <1> 	ja 	short com_i0
  2448                              <1> 	;
  2449                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2450                              <1> 	; 20/11/2015
  2451                              <1> 	; 17/11/2015
  2452                              <1> 	; 16/11/2015
  2453                              <1> 	; 15/11/2015
  2454                              <1> 	; 24/10/2015
  2455                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2456                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2457                              <1> 	; < serial port 1 interrupt handler >
  2458                              <1> 	;
  2459 0000343B FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2460                              <1> com_i0:
  2461                              <1> 	;push	eax ; *
  2462                              <1> 	; 07/11/2015
  2463 0000343D A2[F66F0000]        <1> 	mov 	byte [ccomport], al
  2464                              <1> 	; 09/11/2015
  2465                              <1> 	;movzx	ebx, ax ; 8 or 9
  2466                              <1> 	; 08/01/2022
  2467 00003442 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2468                              <1> 	; 17/11/2015
  2469                              <1>  	; reset request for response status
  2470 00003444 88A3[EC6F0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2471                              <1> 	;
  2472                              <1> 	; 20/11/2015
  2473 0000344A EC                  <1> 	in	al, dx		; read interrupt id. register
  2474 0000344B EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2475 0000344D 2404                <1> 	and	al, 4		; received data available?	
  2476 0000344F 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2477                              <1> 	;
  2478                              <1> 	; 20/11/2015
  2479 00003451 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2480 00003454 EC                  <1> 	in	al, dx     	; read character
  2481                              <1> 	;JMP	$+2	   	; I/O DELAY
  2482                              <1> 	; 08/11/2015
  2483                              <1> 	; 07/11/2015
  2484 00003455 89DE                <1> 	mov	esi, ebx 
  2485 00003457 89DF                <1> 	mov	edi, ebx
  2486 00003459 81C6[F06F0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2487 0000345F 81C7[F26F0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2488 00003465 8806                <1> 	mov	[esi], al ; received char (current char)
  2489                              <1> 	; query
  2490 00003467 20C0                <1> 	and	al, al
  2491 00003469 7527                <1> 	jnz	short com_i2
  2492                              <1>    	; response
  2493                              <1> 	; 17/11/2015
  2494                              <1> 	; set request for response status
  2495 0000346B FE83[EC6F0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2496                              <1> 	;
  2497 00003471 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2498 00003475 EC                  <1> 	in	al, dx	   	; read line status register 
  2499 00003476 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2500 00003478 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2501 0000347A 7445                <1> 	jz	short com_eoi 	; no
  2502 0000347C B0FF                <1> 	mov 	al, 0FFh   	; response			
  2503 0000347E 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2504 00003482 EE                  <1> 	out	dx, al	   	; send on serial port
  2505                              <1> 	; 17/11/2015
  2506 00003483 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2507 00003486 7502                <1> 	jne 	short com_i1    ; no
  2508 00003488 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2509                              <1> com_i1:
  2510                              <1> 	; 17/11/2015
  2511                              <1> 	; reset request for response status (again)
  2512 0000348A FE8B[EC6F0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2513 00003490 EB2F                <1> 	jmp	short com_eoi
  2514                              <1> com_i2:	
  2515                              <1> 	; 08/11/2015
  2516 00003492 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2517 00003494 7417                <1> 	je	short com_i3	; (check for response signal)
  2518                              <1> 	; 07/11/2015
  2519 00003496 3C04                <1> 	cmp	al, 04h	; EOT
  2520 00003498 751C                <1> 	jne	short com_i4	
  2521                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2522                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2523                              <1> 	; 08/11/2015
  2524                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2525 0000349A 861D[B66F0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2526 000034A0 E80BFFFFFF          <1> 	call 	ctrlbrk
  2527 000034A5 861D[B66F0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2528                              <1> 	;mov	al, 04h ; EOT
  2529                              <1> 	; 08/11/2015
  2530 000034AB EB09                <1> 	jmp	short com_i4	
  2531                              <1> com_i3:
  2532                              <1> 	; 08/11/2015
  2533                              <1> 	; If 0FFh has been received just after a query
  2534                              <1> 	; (schar, ZERO), it is a response signal.
  2535                              <1> 	; 17/11/2015
  2536 000034AD 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2537 000034B0 7704                <1> 	ja	short com_i4 ; no
  2538                              <1> 	; reset query status (schar)
  2539 000034B2 8807                <1> 	mov	[edi], al ; 0FFh
  2540 000034B4 FEC0                <1> 	inc	al ; 0
  2541                              <1> com_i4:
  2542                              <1> 	; 27/07/2014
  2543                              <1> 	; 09/07/2014
  2544 000034B6 D0E3                <1> 	shl	bl, 1	
  2545 000034B8 81C3[B86F0000]      <1> 	add	ebx, ttychr
  2546                              <1> 	; 23/07/2014 (always overwrite)
  2547                              <1> 	;;cmp	word [ebx], 0
  2548                              <1> 	;;ja	short com_eoi
  2549                              <1> 	;
  2550 000034BE 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2551                              <1> 			    ; scan code = 0
  2552                              <1> com_eoi:
  2553                              <1> 	;mov	al, 20h
  2554                              <1> 	;out	20h, al	   ; end of interrupt
  2555                              <1> 	;
  2556                              <1> 	; 07/11/2015
  2557                              <1>       	;pop	eax ; *
  2558 000034C1 A0[F66F0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2559                              <1> 	; al = tty number (8 or 9)
  2560 000034C6 E8031B0000          <1>         call	wakeup
  2561                              <1> com_iret:
  2562                              <1> 	; 23/10/2015
  2563 000034CB 5A                  <1> 	pop	edx ; **
  2564 000034CC 59                  <1> 	pop	ecx ; ***
  2565                              <1> 	; 18/11/2015
  2566                              <1> 	;pop	eax ; ****
  2567                              <1> 	;mov	cr3, eax
  2568                              <1> 	;jmp	iiret
  2569 000034CD E9CCD4FFFF          <1> 	jmp	iiretp
  2570                              <1> 
  2571                              <1> ;iiretp: ; 01/09/2015
  2572                              <1> ;	; 28/08/2015
  2573                              <1> ;	pop	eax ; (*) page directory
  2574                              <1> ;	mov	cr3, eax
  2575                              <1> ;iiret:
  2576                              <1> ;	; 22/08/2014
  2577                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2578                              <1> ;	out	20h, al	; 8259 PORT
  2579                              <1> ;	;
  2580                              <1> ;	pop	es
  2581                              <1> ;	pop	ds
  2582                              <1> ;	pop	edi
  2583                              <1> ;	pop	esi
  2584                              <1> ;	pop	ebx ; 29/08/2014
  2585                              <1> ;	pop 	eax
  2586                              <1> ;	iretd
  2587                              <1> 
  2588                              <1> sp_init:
  2589                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2590                              <1> 	; 07/11/2015
  2591                              <1> 	; 29/10/2015
  2592                              <1> 	; 26/10/2015
  2593                              <1> 	; 23/10/2015
  2594                              <1> 	; 29/06/2015
  2595                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2596                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2597                              <1> 	; Initialization of Serial Port Communication Parameters
  2598                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2599                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2600                              <1> 	;
  2601                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2602                              <1> 	;
  2603                              <1> 	; INPUT:  (29/06/2015)
  2604                              <1> 	;	AL = 0 for COM1
  2605                              <1> 	;	     1 for COM2
  2606                              <1> 	;	AH = Communication parameters	
  2607                              <1> 	;
  2608                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2609                              <1> 	;	Bit	4	3	2	1	0
  2610                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2611                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2612                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2613                              <1> 	;		11 = even
  2614                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2615                              <1> 	;		Retro UNIX 386 v1 feature only !
  2616                              <1> 	;	Bit	7    6    5  | Baud rate
  2617                              <1> 	;		------------------------
  2618                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2619                              <1> 	;		0    0    1  | 9600 (12)
  2620                              <1> 	;		0    1    0  | 19200 (6) 
  2621                              <1> 	;		0    1	  1  | 38400 (3) 
  2622                              <1> 	;		1    0	  0  | 14400 (8)
  2623                              <1> 	;		1    0	  1  | 28800 (4)
  2624                              <1> 	;		1    1    0  | 57600 (2)
  2625                              <1> 	;		1    1    1  | 115200 (1) 	
  2626                              <1> 	
  2627                              <1> 	; References:	
  2628                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2629                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2630                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2631                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2632                              <1> 	;
  2633                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2634                              <1> 	;
  2635 000034D2 BB[F26F0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2636 000034D7 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2637                              <1> 	; 29/10/2015
  2638 000034DB 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2639 000034DF E84F000000          <1> 	call	sp_i3	; call A4	
  2640 000034E4 A880                <1> 	test	al, 80h
  2641 000034E6 740E                <1> 	jz	short sp_i0 ; OK..
  2642                              <1> 		; Error !
  2643                              <1> 	;mov	dx, 3F8h
  2644 000034E8 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2645                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2646                              <1> 	; 08/01/2022
  2647 000034EB B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2648 000034ED E841000000          <1> 	call	sp_i3	; call A4	
  2649 000034F2 A880                <1> 	test	al, 80h
  2650 000034F4 7508                <1> 	jnz	short sp_i1
  2651                              <1> sp_i0:
  2652                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2653                              <1>         ; (INT 14h initialization code disables interrupts.)
  2654                              <1> 	;
  2655 000034F6 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2656 000034F9 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2657                              <1> sp_i1:
  2658 000034FE 43                  <1> 	inc	ebx
  2659 000034FF 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2660                              <1> 	; 29/10/2015
  2661                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2662                              <1> 	; 08/01/2022
  2663 00003503 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2664 00003505 E829000000          <1> 	call	sp_i3	; call A4	
  2665 0000350A A880                <1> 	test	al, 80h
  2666 0000350C 740E                <1> 	jz	short sp_i2 ; OK..
  2667                              <1> 		; Error !
  2668                              <1> 	;mov	dx, 2F8h
  2669 0000350E 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2670                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2671                              <1> 	; 08/01/2022
  2672 00003511 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2673 00003513 E81B000000          <1> 	call	sp_i3	; call A4	
  2674 00003518 A880                <1> 	test	al, 80h
  2675 0000351A 7516                <1> 	jnz	short sp_i7
  2676                              <1> sp_i2:
  2677 0000351C C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2678                              <1> sp_i6:
  2679                              <1> 	;; COM2 - enabling IRQ 3
  2680                              <1> 	; 08/01/2022
  2681 0000351F B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2682                              <1> 	; 07/11/2015
  2683                              <1> 	; 26/10/2015
  2684                              <1> 	;pushf
  2685                              <1> 	;cli
  2686                              <1> 	;;
  2687                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2688                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2689                              <1> 	;in	al, dx 	   		; read register
  2690                              <1> 	;JMP	$+2	   		; I/O DELAY
  2691                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2692                              <1> 	;out	dx, al     		; write back to register
  2693                              <1> 	;JMP	$+2	   		; I/O DELAY
  2694                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2695                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2696                              <1> 	;in	al, dx     		; read register
  2697                              <1> 	;JMP	$+2	   		; I/O DELAY
  2698                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2699                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2700                              <1> 	;out	dx, al 	   		; write back to register
  2701                              <1> 	;JMP	$+2        		; I/O DELAY
  2702                              <1> 	;in	al, 21h    		; read interrupt mask register
  2703                              <1> 	;JMP	$+2	   		; I/O DELAY
  2704                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2705                              <1> 	;out	21h, al    		; write back to register
  2706                              <1> 	;
  2707                              <1> 	; 08/01/2022
  2708 00003521 9C                  <1> 	pushf
  2709 00003522 E8AA000000          <1> 	call	sp_i8
  2710                              <1> 	; 23/10/2015
  2711 00003527 B8[06340000]        <1> 	mov 	eax, com2_int
  2712 0000352C A3[C5390000]        <1> 	mov	[com2_irq3], eax
  2713                              <1> 	; 26/10/2015
  2714 00003531 9D                  <1> 	popf	
  2715                              <1> sp_i7:
  2716 00003532 C3                  <1> 	retn
  2717                              <1> 
  2718                              <1> sp_i3:
  2719                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2720                              <1> 	; 28/10/2015
  2721 00003533 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2722 00003535 B000                <1> 	mov	al, 0
  2723 00003537 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2724 00003538 EB00                <1> 	JMP	$+2			; I/O DELAY
  2725 0000353A 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2726 0000353D B080                <1> 	mov	al, 80h			
  2727 0000353F EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2728                              <1> 	;-----	SET BAUD RATE DIVISOR
  2729                              <1> 	; 26/10/2015
  2730 00003540 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2731                              <1> 					; of the divisor value
  2732 00003543 88C8                <1> 	mov	al, cl	; 1
  2733 00003545 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2734                              <1> 					; 2 = 57600 baud
  2735                              <1> 					; 3 = 38400 baud
  2736                              <1> 					; 6 = 19200 baud
  2737                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2738 00003546 EB00                <1> 	JMP	$+2			; I/O DELAY
  2739 00003548 28C0                <1> 	sub	al, al
  2740 0000354A FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2741                              <1> 					; of the divisor value
  2742 0000354C EE                  <1> 	out	dx, al ; 0
  2743 0000354D EB00                <1> 	JMP	$+2			; I/O DELAY
  2744                              <1> 	;	
  2745 0000354F 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2746                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2747 00003551 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2748 00003554 EE                  <1> 	out	dx, al			
  2749 00003555 EB00                <1> 	JMP	$+2			; I/O DELAY
  2750                              <1> 	; 29/10/2015
  2751 00003557 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2752 00003559 30C0                <1> 	xor	al, al			; 0
  2753 0000355B EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2754 0000355C EB00                <1> 	JMP	$+2	
  2755                              <1> sp_i4:
  2756                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2757                              <1> 	; 29/06/2015 (line status after modem status)
  2758 0000355E 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2759                              <1> sp_i4s:
  2760 00003561 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2761 00003562 EB00                <1> 	JMP	$+2			; I/O DELAY
  2762 00003564 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2763 00003566 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2764                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2765 00003568 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2766                              <1> 	; AL = Line status, AH = Modem status
  2767 00003569 C3                  <1> 	retn
  2768                              <1> 
  2769                              <1> sp_status:
  2770                              <1> 	; 29/06/2015
  2771                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2772                              <1> 	; Get serial port status
  2773 0000356A 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2774 0000356E 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2775                              <1> 					; dx = 2FEh for COM2
  2776 00003570 EBEF                <1> 	jmp	short sp_i4s
  2777                              <1> 
  2778                              <1> sp_setp: ; Set serial port communication parameters
  2779                              <1> 	; 08/01/2022
  2780                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2781                              <1> 	; 07/11/2015
  2782                              <1> 	; 29/10/2015
  2783                              <1> 	; 29/06/2015
  2784                              <1> 	; Retro UNIX 386 v1 feature only !	
  2785                              <1> 	;
  2786                              <1> 	; INPUT:
  2787                              <1> 	;	AL = 0 for COM1
  2788                              <1> 	;	     1 for COM2
  2789                              <1> 	;	AH = Communication parameters (*)
  2790                              <1> 	; OUTPUT:
  2791                              <1> 	;	CL = Line status
  2792                              <1> 	;	CH = Modem status
  2793                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2794                              <1> 	;		 'invalid parameter !' 
  2795                              <1> 	;		 	 or
  2796                              <1> 	;		 'device not ready !' error
  2797                              <1> 	;	
  2798                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2799                              <1> 	;	Bit	4	3	2	1	0
  2800                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2801                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2802                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2803                              <1> 	;		11 = even
  2804                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2805                              <1> 	;		Retro UNIX 386 v1 feature only !
  2806                              <1> 	;	Bit	7    6    5  | Baud rate
  2807                              <1> 	;		------------------------
  2808                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2809                              <1> 	;		0    0    1  | 9600 (12)
  2810                              <1> 	;		0    1    0  | 19200 (6) 
  2811                              <1> 	;		0    1	  1  | 38400 (3) 
  2812                              <1> 	;		1    0	  0  | 14400 (8)
  2813                              <1> 	;		1    0	  1  | 28800 (4)
  2814                              <1> 	;		1    1    0  | 57600 (2)
  2815                              <1> 	;		1    1    1  | 115200 (1) 
  2816                              <1> 	;
  2817                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2818                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2819                              <1> 	;
  2820                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2821                              <1> 	;
  2822 00003572 66BAF803            <1> 	mov	dx, 3F8h
  2823 00003576 BB[F26F0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2824 0000357B 3C01                <1> 	cmp	al, 1
  2825 0000357D 7770                <1> 	ja 	short sp_invp_err
  2826 0000357F 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2827 00003581 FECE                <1> 	dec	dh ; 2F8h
  2828 00003583 43                  <1> 	inc	ebx ; COM2 control byte offset
  2829                              <1> sp_setp1:
  2830                              <1> 	; 29/10/2015
  2831 00003584 8823                <1> 	mov	[ebx], ah
  2832 00003586 0FB6CC              <1> 	movzx 	ecx, ah
  2833 00003589 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2834 0000358C 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2835 0000358F 8A81[FE350000]      <1> 	mov	al, [ecx+b_div_tbl]
  2836 00003595 6689C1              <1> 	mov	cx, ax
  2837 00003598 E896FFFFFF          <1> 	call	sp_i3
  2838 0000359D 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2839 000035A0 A880                <1> 	test	al, 80h
  2840 000035A2 740F                <1> 	jz	short sp_setp2
  2841 000035A4 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2842                              <1> stp_dnr_err:
  2843 000035A7 C705[1C750000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2843 000035AF 0000                <1>
  2844                              <1> 	; CL = Line status, CH = Modem status
  2845 000035B1 F9                  <1> 	stc
  2846 000035B2 C3                  <1> 	retn
  2847                              <1> sp_setp2:
  2848 000035B3 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2849                              <1>         ;jna	sp_i6
  2850                              <1> 		      ; COM1 (3F?h)
  2851                              <1> 	; 24/12/2021
  2852 000035B6 7705                <1> 	ja	short sp_i5
  2853 000035B8 E962FFFFFF          <1> 	jmp	sp_i6
  2854                              <1> sp_i5: 
  2855                              <1> 	; 08/01/2022
  2856 000035BD B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2857                              <1> 	; 07/11/2015
  2858                              <1> 	; 26/10/2015
  2859                              <1> 	; 29/06/2015
  2860                              <1> 	;
  2861                              <1> 	;; COM1 - enabling IRQ 4
  2862                              <1> 	;pushf
  2863                              <1> 	;cli
  2864                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2865                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2866                              <1> 	;in	al, dx 	   		; read register
  2867                              <1> 	;JMP	$+2			; I/O DELAY
  2868                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2869                              <1> 	;out	dx, al     		; write back to register
  2870                              <1> 	;JMP	$+2			; I/O DELAY
  2871                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2872                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2873                              <1> 	;in	al, dx     		; read register
  2874                              <1> 	;JMP	$+2			; I/O DELAY
  2875                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2876                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2877                              <1> 	;out	dx, al 	   		; write back to register
  2878                              <1> 	;JMP	$+2        		; I/O DELAY
  2879                              <1> 	;in	al, 21h    		; read interrupt mask register
  2880                              <1> 	;JMP	$+2			; I/O DELAY
  2881                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2882                              <1> 	;out	21h, al    		; write back to register
  2883                              <1> 	;
  2884                              <1> 	; 08/01/2022
  2885 000035BF 9C                  <1> 	pushf
  2886 000035C0 E80C000000          <1> 	call	sp_i8
  2887                              <1> 	; 23/10/2015
  2888 000035C5 B8[0F340000]        <1> 	mov 	eax, com1_int
  2889 000035CA A3[C1390000]        <1> 	mov	[com1_irq4], eax
  2890                              <1> 	; 26/10/2015
  2891 000035CF 9D                  <1> 	popf
  2892 000035D0 C3                  <1> 	retn
  2893                              <1> 
  2894                              <1> sp_i8:
  2895                              <1> 	; 08/01/2022
  2896                              <1> 	;pushf
  2897 000035D1 FA                  <1> 	cli
  2898                              <1> 	;
  2899                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2900 000035D2 B2FC                <1> 	mov	dl, 0FCh
  2901 000035D4 EC                  <1> 	in	al, dx 	   		; read register
  2902 000035D5 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2903 000035D7 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2904 000035D9 EE                  <1> 	out	dx, al     		; write back to register
  2905 000035DA EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2906                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2907 000035DC B2F9                <1> 	mov	dl, 0F9h
  2908 000035DE EC                  <1> 	in	al, dx     		; read register
  2909 000035DF EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2910                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2911 000035E1 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2912 000035E3 EE                  <1> 	out	dx, al 	   		; write back to register
  2913 000035E4 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2914 000035E6 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2915 000035E8 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2916                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2917 000035EA 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2918 000035EC E621                <1> 	out	21h, al    		; write back to register
  2919                              <1> 	;
  2920                              <1> 	;popf	
  2921 000035EE C3                  <1> 	retn
  2922                              <1> 
  2923                              <1> sp_invp_err:
  2924 000035EF C705[1C750000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2924 000035F7 0000                <1>
  2925 000035F9 31C9                <1> 	xor	ecx, ecx
  2926 000035FB 49                  <1> 	dec	ecx ; 0FFFFh
  2927 000035FC F9                  <1> 	stc
  2928 000035FD C3                  <1> 	retn
  2929                              <1> 
  2930                              <1> ; 29/10/2015
  2931                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2932 000035FE 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2933                              <1> 
  2934                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2935                              <1> epoch:
  2936                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2937                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2938                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2939                              <1> 	; 'epoch' procedure prototype: 
  2940                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2941                              <1> 	; 14/11/2012
  2942                              <1> 	; unixboot.asm (boot file configuration)
  2943                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2944                              <1> 	; 21/7/2012
  2945                              <1> 	; 15/7/2012
  2946                              <1> 	; 14/7/2012		
  2947                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2948                              <1> 	; compute current date and time as UNIX Epoch/Time
  2949                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2950                              <1> 	;
  2951                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2952                              <1> 	;
  2953 00003605 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2954 0000360A 86E9                <1>         xchg 	ch,cl
  2955 0000360C 66890D[F66C0000]    <1>         mov 	[hour], cx
  2956 00003613 86F2                <1>         xchg 	dh,dl
  2957 00003615 668915[FA6C0000]    <1>         mov 	[second], dx
  2958                              <1> 	;
  2959 0000361C E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2960 00003621 86E9                <1>         xchg 	ch,cl
  2961 00003623 66890D[F06C0000]    <1>         mov 	[year], cx
  2962 0000362A 86F2                <1>         xchg 	dh,dl
  2963 0000362C 668915[F26C0000]    <1>         mov 	[month], dx
  2964                              <1> 	;
  2965 00003633 66B93030            <1> 	mov 	cx, 3030h
  2966                              <1> 	;
  2967 00003637 A0[F66C0000]        <1> 	mov 	al, [hour] ; Hour
  2968                              <1>         	; AL <= BCD number)
  2969 0000363C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2970                              <1> 					; AH = AL / 10h
  2971                              <1> 					; AL = AL MOD 10h
  2972 0000363E D50A                <1>         aad 	; AX= AH*10+AL
  2973 00003640 A2[F66C0000]        <1> 	mov 	[hour], al
  2974 00003645 A0[F76C0000]        <1> 	mov 	al, [hour+1] ; Minute
  2975                              <1>         	; AL <= BCD number)
  2976 0000364A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2977                              <1> 					; AH = AL / 10h
  2978                              <1> 					; AL = AL MOD 10h
  2979 0000364C D50A                <1>         aad 	; AX= AH*10+AL
  2980 0000364E A2[F86C0000]        <1> 	mov 	[minute], al
  2981 00003653 A0[FA6C0000]        <1> 	mov 	al, [second] ; Second
  2982                              <1>         	; AL <= BCD number)
  2983 00003658 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2984                              <1> 					; AH = AL / 10h
  2985                              <1> 					; AL = AL MOD 10h
  2986 0000365A D50A                <1>         aad 	; AX= AH*10+AL
  2987 0000365C A2[FA6C0000]        <1> 	mov 	[second], al
  2988 00003661 66A1[F06C0000]      <1> 	mov 	ax, [year] ; Year (century)
  2989                              <1> 	;push 	ax
  2990                              <1> 	; 04/12/2021
  2991 00003667 50                  <1> 	push	eax
  2992                              <1> 	   	; AL <= BCD number)
  2993 00003668 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2994                              <1> 					; AH = AL / 10h
  2995                              <1> 					; AL = AL MOD 10h
  2996 0000366A D50A                <1>         aad 	; AX= AH*10+AL
  2997 0000366C B464                <1> 	mov 	ah, 100
  2998 0000366E F6E4                <1> 	mul 	ah
  2999 00003670 66A3[F06C0000]      <1> 	mov 	[year], ax
  3000                              <1> 	;pop	ax
  3001                              <1> 	; 04/12/2021
  3002 00003676 58                  <1> 	pop	eax
  3003 00003677 88E0                <1> 	mov	al, ah
  3004                              <1>         	; AL <= BCD number)
  3005 00003679 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3006                              <1> 					; AH = AL / 10h
  3007                              <1> 					; AL = AL MOD 10h
  3008 0000367B D50A                <1>         aad 	; AX= AH*10+AL
  3009 0000367D 660105[F06C0000]    <1> 	add 	[year], ax
  3010 00003684 A0[F26C0000]        <1> 	mov 	al, [month] ; Month
  3011                              <1>            	; AL <= BCD number)
  3012 00003689 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3013                              <1> 					; AH = AL / 10h
  3014                              <1> 					; AL = AL MOD 10h
  3015 0000368B D50A                <1>         aad 	; AX= AH*10+AL
  3016 0000368D A2[F26C0000]        <1> 	mov 	[month], al	
  3017 00003692 A0[F36C0000]        <1>         mov     al, [month+1]      	; Day
  3018                              <1>            	; AL <= BCD number)
  3019 00003697 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3020                              <1> 					; AH = AL / 10h
  3021                              <1> 					; AL = AL MOD 10h
  3022 00003699 D50A                <1>         aad 	; AX= AH*10+AL
  3023 0000369B A2[F46C0000]        <1>         mov     [day], al
  3024                              <1> 	
  3025                              <1> convert_to_epoch:
  3026                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3027                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3028                              <1> 	;
  3029                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3030                              <1> 	;
  3031                              <1> 	; Derived from DALLAS Semiconductor
  3032                              <1> 	; Application Note 31 (DS1602/DS1603)
  3033                              <1> 	; 6 May 1998
  3034 000036A0 29C0                <1> 	sub 	eax, eax
  3035 000036A2 66A1[F06C0000]      <1> 	mov 	ax, [year]
  3036 000036A8 662DB207            <1> 	sub 	ax, 1970
  3037 000036AC BA6D010000          <1> 	mov 	edx, 365
  3038 000036B1 F7E2                <1> 	mul 	edx
  3039 000036B3 31DB                <1> 	xor 	ebx, ebx
  3040 000036B5 8A1D[F26C0000]      <1> 	mov 	bl, [month]
  3041 000036BB FECB                <1> 	dec 	bl
  3042 000036BD D0E3                <1> 	shl 	bl, 1
  3043                              <1> 	;sub	edx, edx
  3044 000036BF 668B93[FC6C0000]    <1> 	mov 	dx, [EBX+DMonth]
  3045 000036C6 8A1D[F46C0000]      <1>         mov     bl, [day]
  3046 000036CC FECB                <1> 	dec 	bl
  3047 000036CE 01D0                <1> 	add 	eax, edx
  3048 000036D0 01D8                <1> 	add 	eax, ebx
  3049                              <1> 			; EAX = days since 1/1/1970
  3050 000036D2 668B15[F06C0000]    <1> 	mov 	dx, [year]
  3051 000036D9 6681EAB107          <1> 	sub 	dx, 1969
  3052 000036DE 66D1EA              <1> 	shr 	dx, 1
  3053 000036E1 66D1EA              <1> 	shr 	dx, 1		
  3054                              <1> 		; (year-1969)/4
  3055 000036E4 01D0                <1> 	add 	eax, edx
  3056                              <1> 			; + leap days since 1/1/1970
  3057 000036E6 803D[F26C0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3058 000036ED 7610                <1> 	jna 	short cte1
  3059 000036EF 668B15[F06C0000]    <1> 	mov 	dx, [year]
  3060 000036F6 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3061 000036FA 7503                <1> 	jnz 	short cte1		
  3062                              <1> 			; and if leap year
  3063 000036FC 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3064                              <1> cte1: 			; compute seconds since 1/1/1970
  3065 000036FF BA18000000          <1> 	mov 	edx, 24
  3066 00003704 F7E2                <1> 	mul	edx
  3067 00003706 8A15[F66C0000]      <1> 	mov 	dl, [hour]
  3068 0000370C 01D0                <1> 	add 	eax, edx
  3069                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3070                              <1> 	;mov	ebx, 60
  3071 0000370E B33C                <1> 	mov	bl, 60
  3072 00003710 F7E3                <1> 	mul	ebx
  3073 00003712 8A15[F86C0000]      <1> 	mov 	dl, [minute]
  3074 00003718 01D0                <1> 	add 	eax, edx
  3075                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3076                              <1> 	;mov 	ebx, 60
  3077 0000371A F7E3                <1> 	mul	ebx
  3078 0000371C 8A15[FA6C0000]      <1> 	mov 	dl, [second]
  3079 00003722 01D0                <1> 	add 	eax, edx
  3080                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3081 00003724 C3                  <1> 	retn
  3082                              <1> 
  3083                              <1> get_rtc_time:
  3084                              <1> 	; 15/03/2015
  3085                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3086                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3087                              <1> 	; INT 1Ah
  3088                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3089                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3090                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3091                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3092                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3093                              <1> 	;								
  3094                              <1> RTC_20: 				; GET RTC TIME
  3095 00003725 FA                  <1> 	cli
  3096 00003726 E807D4FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3097 0000372B 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3098                              <1> 
  3099 0000372D B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3100 0000372F E8E8D3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3101 00003734 88C6                <1> 	MOV	DH, AL			; SAVE
  3102 00003736 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3103 00003738 E8DFD3FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3104 0000373D 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3105 0000373F 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3106 00003741 B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3107 00003743 E8D4D3FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3108 00003748 88C1                <1> 	MOV	CL, AL			; SAVE
  3109 0000374A B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3110 0000374C E8CBD3FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3111 00003751 88C5                <1> 	MOV	CH, AL			; SAVE
  3112 00003753 F8                  <1> 	CLC				; SET CY= 0
  3113                              <1> RTC_29:
  3114 00003754 FB                  <1> 	sti
  3115 00003755 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3116                              <1> 
  3117                              <1> get_rtc_date:
  3118                              <1> 	; 15/03/2015
  3119                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3120                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3121                              <1> 	; INT 1Ah
  3122                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3123                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3124                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3125                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3126                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3127                              <1> 	;
  3128                              <1> RTC_40: 				; GET RTC DATE
  3129 00003756 FA                  <1> 	cli
  3130 00003757 E8D6D3FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3131 0000375C 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3132                              <1> 
  3133 0000375E B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3134 00003760 E8B7D3FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3135 00003765 88C2                <1> 	MOV	DL, AL			; SAVE
  3136 00003767 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3137 00003769 E8AED3FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3138 0000376E 88C6                <1> 	MOV	DH, AL			; SAVE
  3139 00003770 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3140 00003772 E8A5D3FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3141 00003777 88C1                <1> 	MOV	CL, AL			; SAVE
  3142 00003779 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3143 0000377B E89CD3FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3144 00003780 88C5                <1> 	MOV	CH, AL			; SAVE
  3145 00003782 F8                  <1> 	CLC				; SET CY=0
  3146                              <1> RTC_49:
  3147 00003783 FB                  <1> 	sti
  3148 00003784 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3149                              <1> 
  3150                              <1> set_date_time:
  3151                              <1> convert_from_epoch:
  3152                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3153                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3154                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3155                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3156                              <1> 	;
  3157                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3158                              <1> 	;
  3159                              <1> 	; Derived from DALLAS Semiconductor
  3160                              <1> 	; Application Note 31 (DS1602/DS1603)
  3161                              <1> 	; 6 May 1998
  3162                              <1> 	;
  3163                              <1> 	; INPUT:
  3164                              <1> 	; EAX = Unix (Epoch) Time
  3165                              <1> 	;
  3166 00003785 31D2                <1> 	xor 	edx, edx
  3167 00003787 B93C000000          <1> 	mov 	ecx, 60
  3168 0000378C F7F1                <1> 	div	ecx
  3169                              <1> 	;mov 	[imin], eax   ; whole minutes
  3170                              <1> 			  ; since 1/1/1970
  3171 0000378E 668915[FA6C0000]    <1> 	mov 	[second], dx  ; leftover seconds
  3172 00003795 29D2                <1> 	sub 	edx, edx
  3173 00003797 F7F1                <1> 	div	ecx
  3174                              <1> 	;mov 	[ihrs], eax   ; whole hours
  3175                              <1> 	;		      ; since 1/1/1970
  3176 00003799 668915[F86C0000]    <1> 	mov 	[minute], dx  ; leftover minutes
  3177 000037A0 31D2                <1> 	xor	edx, edx
  3178                              <1> 	;mov 	cx, 24
  3179 000037A2 B118                <1> 	mov 	cl, 24
  3180 000037A4 F7F1                <1> 	div	ecx
  3181                              <1> 	;mov 	[iday], ax   ; whole days
  3182                              <1> 			     ; since 1/1/1970
  3183 000037A6 668915[F66C0000]    <1> 	mov 	[hour], dx   ; leftover hours
  3184 000037AD 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3185                              <1> 			     ; 1/1/1968 	
  3186                              <1> 	;mov 	[iday], ax
  3187 000037B2 50                  <1> 	push 	eax
  3188 000037B3 29D2                <1> 	sub	edx, edx
  3189 000037B5 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3190 000037BA F7F1                <1> 	div	ecx
  3191 000037BC 59                  <1> 	pop 	ecx
  3192                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3193 000037BD 6652                <1> 	push 	dx
  3194                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3195 000037BF 6683FA3C            <1> 	cmp 	dx, 31 + 29  ; if past feb 29 then
  3196 000037C3 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3197 000037C4 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3198                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3199                              <1> 	;mov 	cx, [iday]
  3200 000037C7 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3201 000037C8 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3202 000037CA B96D010000          <1> 	mov 	ecx, 365
  3203 000037CF 31D2                <1> 	xor	edx, edx
  3204                              <1> 	; EAX = iday-lday, EDX = 0
  3205 000037D1 F7F1                <1> 	div	ecx
  3206                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3207                              <1> 	;jday = iday - (iyrs*365) - lday
  3208                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3209                              <1> 	;add	eax, 1968
  3210 000037D3 6605B007            <1> 	add 	ax, 1968     ; compute year
  3211 000037D7 66A3[F06C0000]      <1> 	mov 	[year], ax
  3212 000037DD 6689D1              <1> 	mov 	cx, dx
  3213                              <1> 	;mov 	dx, [qday]
  3214 000037E0 665A                <1> 	pop 	dx
  3215 000037E2 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3216 000037E7 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3217 000037E9 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3218 000037ED F5                  <1>         cmc		     ; add a leap day to the # of whole
  3219 000037EE 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3220                              <1> cfe1:			
  3221                              <1> 	;mov 	[jday], cx
  3222 000037F2 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3223 000037F6 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3224 000037FA 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3225                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3226 000037FE 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3227 00003801 731D                <1> 	jnb 	short cfe3
  3228 00003803 664B                <1> 	dec 	bx           ; month = month - 1
  3229 00003805 66D1E3              <1> 	shl 	bx, 1 
  3230 00003808 668B93[FC6C0000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3231 0000380F 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3232 00003812 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3233 00003816 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3234 00003818 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3235 0000381A 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3236 0000381C 6642                <1> 	inc 	dx           ; mday = mday + 1
  3237 0000381E EBDE                <1> 	jmp 	short cfe2
  3238                              <1> cfe3:
  3239 00003820 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3240 00003822 66891D[F26C0000]    <1> 	mov 	[month], bx
  3241 00003829 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3242 0000382C 6641                <1> 	inc 	cx 			  
  3243 0000382E 66890D[F46C0000]    <1> 	mov 	[day], cx
  3244                              <1> 	
  3245                              <1> 	; eax, ebx, ecx, edx is changed at return
  3246                              <1> 	; output ->
  3247                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3248                              <1> 	
  3249                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3250                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3251                              <1> set_date:
  3252 00003835 A0[F16C0000]        <1>         mov     al, [year+1]
  3253 0000383A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3254 0000383C D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3255                              <1> 			     ; AL = AH * 10h + AL
  3256 0000383E 88C5                <1> 	mov 	ch, al ; century (BCD)
  3257 00003840 A0[F06C0000]        <1> 	mov 	al, [year]
  3258 00003845 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3259 00003847 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3260                              <1> 			     ; AL = AH * 10h + AL
  3261 00003849 88C1                <1> 	mov 	cl, al ; year (BCD)
  3262 0000384B A0[F26C0000]        <1>         mov 	al, [month]
  3263 00003850 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3264 00003852 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3265                              <1> 			     ; AL = AH * 10h + AL
  3266 00003854 88C6                <1> 	mov 	dh, al ; month (BCD)
  3267 00003856 A0[F46C0000]        <1> 	mov 	al, [day]
  3268 0000385B D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3269 0000385D D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3270                              <1> 			     ; AL = AH * 10h + AL
  3271 0000385F 88C6                <1> 	mov 	dh, al ; day (BCD)
  3272                              <1> 	; Set real-time clock date
  3273 00003861 E879000000          <1> 	call	set_rtc_date
  3274                              <1> set_time:
  3275                              <1>         ; Read real-time clock time 
  3276                              <1> 	; (get day light saving time bit status)
  3277 00003866 FA                  <1>  	cli
  3278 00003867 E8C6D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3279                              <1> 	; cf = 1 -> al = 0
  3280 0000386C 7207                <1>         jc      short stime1
  3281 0000386E B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3282 00003870 E8A7D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3283                              <1> stime1:
  3284 00003875 FB                  <1> 	sti
  3285 00003876 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3286 00003878 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3287                              <1> 	; DL = 1 or 0 (day light saving time)
  3288                              <1> 	;	
  3289 0000387A A0[F66C0000]        <1> 	mov 	al, [hour]
  3290 0000387F D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3291 00003881 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3292                              <1> 			     ; AL = AH * 10h + AL
  3293 00003883 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3294 00003885 A0[F86C0000]        <1>         mov     al, [minute]
  3295 0000388A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3296 0000388C D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3297                              <1> 			     ; AL = AH * 10h + AL
  3298 0000388E 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3299 00003890 A0[FA6C0000]        <1>         mov     al, [second]
  3300 00003895 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3301 00003897 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3302                              <1> 			     ; AL = AH * 10h + AL
  3303 00003899 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3304                              <1> 	; Set real-time clock time
  3305                              <1>  	; call	set_rtc_time
  3306                              <1> set_rtc_time:
  3307                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3308                              <1> 	; 15/03/2015
  3309                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3310                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3311                              <1> 	; INT 1Ah
  3312                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3313                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3314                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3315                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3316                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3317                              <1> 	;								:
  3318                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3319                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3320                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3321                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3322                              <1> 	;
  3323                              <1> RTC_30: 				; SET RTC TIME
  3324 0000389B FA                  <1> 	cli
  3325 0000389C E891D2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3326 000038A1 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3327 000038A3 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3328                              <1> RTC_35:
  3329 000038A8 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3330 000038AA B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3331 000038AC E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3332 000038B1 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3333 000038B3 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3334 000038B5 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3335 000038BA 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3336 000038BC B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3337 000038BE E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3338                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3339 000038C3 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3340 000038C7 E850D2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3341 000038CC 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3342 000038CE 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3343 000038D0 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3344 000038D3 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3345 000038D5 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3346 000038D7 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3347 000038DC F8                  <1> 	CLC				; SET CY= 0
  3348 000038DD FB                  <1> 	sti
  3349 000038DE C3                  <1> 	RETn				; RETURN WITH CY= 0
  3350                              <1> 
  3351                              <1> set_rtc_date:
  3352                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3353                              <1> 	; 15/03/2015
  3354                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3355                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3356                              <1> 	; INT 1Ah
  3357                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3358                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3359                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3360                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3361                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3362                              <1> 	;
  3363                              <1> RTC_50: 				; SET RTC DATE
  3364 000038DF FA                  <1> 	cli
  3365 000038E0 E84DD2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3366 000038E5 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3367 000038E7 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3368                              <1> RTC_55:
  3369 000038EC 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3370 000038F0 E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3371 000038F5 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3372 000038F7 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3373 000038F9 E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3374 000038FE 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3375 00003900 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3376 00003902 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3377 00003907 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3378 00003909 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3379 0000390B E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3380 00003910 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3381 00003912 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3382 00003914 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3383                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3384 00003919 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3385 0000391D E8FAD1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3386 00003922 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3387 00003924 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3388 00003926 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3389 0000392B F8                  <1> 	CLC				; SET CY= 0
  3390 0000392C FB                  <1> 	sti
  3391 0000392D C3                  <1> 	RETn				; RETURN CY=0
  3392                              <1> 
  3393                              <1> 	; 15/03/2015
  3394                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3395 0000392E B426                <1> 	mov	ah, 26h
  3396 00003930 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3397 00003932 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3398 00003937 B482                <1> 	mov	ah, 82h
  3399 00003939 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3400 0000393B E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3401 00003940 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3402 00003942 E8D5D1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3403 00003947 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3404                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3405                              <1> 	;RETn
  3406                              <1> 	; 06/02/2022
  3407 00003949 E9CED1FFFF          <1> 	jmp	CMOS_READ
  3408                              <1> 
  3409                              <1> 	; 15/03/2015
  3410                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3411                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3412 0000394E 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3413                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3414 0000394F D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3415 00003951 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3416 00003952 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3417 00003954 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3418 00003955 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3419 00003957 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3420 00003959 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3421 0000395B B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3422 0000395D D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3423 0000395F E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3424 00003961 90                  <1> 	nop			; I/O DELAY
  3425 00003962 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3426                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3427 00003964 9D                  <1> 	popf	
  3428 00003965 C3                  <1> 	RETn
  3429                              <1> 
  3430                              <1> bf_init:
  3431                              <1> 	; 28/11/2021
  3432                              <1> 	; 14/08/2015
  3433                              <1> 	; 02/07/2015
  3434                              <1> 	; 01/07/2015
  3435                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3436                              <1> 	; Buffer (pointer) initialization !
  3437                              <1> 	; 
  3438                              <1> 	; 17/07/2013 - 24/07/2013
  3439                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3440                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3441                              <1> 	;
  3442 00003966 BF[64740000]        <1> 	mov	edi, bufp 
  3443 0000396B B8[8C890000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3444 00003970 29D2                <1> 	sub	edx, edx
  3445 00003972 FECA                <1> 	dec	dl
  3446 00003974 31C9                <1> 	xor	ecx, ecx
  3447 00003976 49                  <1> 	dec	ecx
  3448                              <1> bi0:
  3449 00003977 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3450 0000397C AB                  <1> 	stosd
  3451 0000397D 89C6                <1> 	mov	esi, eax
  3452 0000397F 8916                <1> 	mov	[esi], edx ; 000000FFh
  3453                              <1> 			    ; Not a valid device sign
  3454 00003981 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3455                              <1> 		      ; Not a valid block number sign 	 	
  3456 00003984 3D[5C7D0000]        <1> 	cmp	eax, buffer
  3457 00003989 77EC                <1> 	ja	short bi0
  3458 0000398B B8[4C750000]        <1> 	mov	eax, sb0
  3459 00003990 AB                  <1> 	stosd
  3460 00003991 B8[54770000]        <1> 	mov	eax, sb1
  3461 00003996 AB                  <1> 	stosd
  3462 00003997 89C6                <1> 	mov	esi, eax ; offset sb1
  3463 00003999 8916                <1> 	mov	[esi], edx ; 000000FFh
  3464                              <1> 			    ; Not a valid device sign
  3465 0000399B 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3466                              <1> 		      ; Not a valid block number sign 	 
  3467                              <1> 	; 14/08/2015
  3468                              <1> 	;call 	rdev_init
  3469                              <1> 	;retn
  3470                              <1> 
  3471                              <1> 	; 28/11/2021
  3472                              <1> rdev_init: ; root device, super block buffer initialization
  3473                              <1> 	; 14/08/2015
  3474                              <1> 	; Retro UNIX 386 v1 feature only !
  3475                              <1> 	;
  3476                              <1> 	; NOTE: Disk partitions (file systems), logical
  3477                              <1> 	; drive initialization, partition's start sector etc.
  3478                              <1> 	; will be coded here, later in 'ldrv_init'	
  3479                              <1> 
  3480 0000399E 0FB605[7A6A0000]    <1> 	movzx	eax, byte [boot_drv]
  3481                              <1> rdi_0:
  3482 000039A5 3C80                <1> 	cmp	al, 80h
  3483 000039A7 7202                <1> 	jb	short rdi_1
  3484 000039A9 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3485                              <1> rdi_1:
  3486 000039AB A2[8A740000]        <1> 	mov	[rdev], al
  3487 000039B0 BB[4C750000]        <1>         mov	ebx, sb0 ; super block buffer
  3488 000039B5 8903                <1> 	mov 	[ebx], eax
  3489 000039B7 B001                <1> 	mov	al, 1 ; eax = 1
  3490 000039B9 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3491                              <1> 	;call 	diskio
  3492                              <1> 	;retn
  3493                              <1> 	; 28/11/2021
  3494 000039BC E929290000          <1> 	jmp	diskio
  3495                              <1> 
  3496                              <1> ; 23/10/2015
  3497                              <1> com1_irq4:
  3498 000039C1 [C9390000]          <1> 	dd dummy_retn
  3499                              <1> com2_irq3:
  3500 000039C5 [C9390000]          <1> 	dd dummy_retn
  3501                              <1> 
  3502                              <1> dummy_retn:
  3503 000039C9 C3                  <1> 	retn
  2072                                  %include 'u1.s'      ; 10/05/2015
  2073                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2074                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2075                              <1> ; ****************************************************************************
  2076                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2077                              <1> ; Last Modification: 11/02/2022
  2078                              <1> ; ----------------------------------------------------------------------------
  2079                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2080                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2081                              <1> ;
  2082                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2083                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2084                              <1> ; <Bell Laboratories (17/3/1972)>
  2085                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2086                              <1> ;
  2087                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2088                              <1> ;
  2089                              <1> ; ****************************************************************************
  2090                              <1> 
  2091                              <1> unkni: ; / used for all system calls
  2092                              <1> sysent: ; < enter to system call >
  2093                              <1> 	; 25/12/2021 (Retro UNIX 386 v1.2)
  2094                              <1> 	; 19/10/2015
  2095                              <1> 	; 21/09/2015
  2096                              <1> 	; 01/07/2015
  2097                              <1> 	; 19/05/2015
  2098                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2099                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2100                              <1> 	;
  2101                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2102                              <1> 	; The trap type is determined and an indirect jump is made to 
  2103                              <1> 	; the appropriate system call handler. If there is a trap inside
  2104                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2105                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2106                              <1> 	; instructor is decoded to get the the system code part (see
  2107                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2108                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2109                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2110                              <1> 	; is called. If the call is legitimate control passes to the
  2111                              <1> 	; appropriate system routine.
  2112                              <1> 	;
  2113                              <1> 	; Calling sequence:
  2114                              <1> 	;	Through a trap caused by any sys call outside the system.
  2115                              <1> 	; Arguments:
  2116                              <1> 	;	Arguments of particular system call.	
  2117                              <1> 	; ...............................................................
  2118                              <1> 	;	
  2119                              <1> 	; Retro UNIX 8086 v1 modification: 
  2120                              <1> 	;       System call number is in EAX register.
  2121                              <1> 	;
  2122                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2123                              <1> 	;	registers depending of function details.
  2124                              <1>   	;
  2125                              <1> 	; 16/04/2015
  2126 000039CA 368925[A0740000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2127                              <1> 	; save user registers
  2128 000039D1 1E                  <1> 	push	ds
  2129 000039D2 06                  <1> 	push	es
  2130 000039D3 0FA0                <1> 	push	fs
  2131 000039D5 0FA8                <1> 	push	gs
  2132 000039D7 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2133                              <1> 	;
  2134                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2135                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2136                              <1> 	;	for saving/restoring user registers.)
  2137                              <1> 	;
  2138 000039D8 50                  <1> 	push	eax ; 01/07/2015
  2139 000039D9 66B81000            <1> 	mov     ax, KDATA
  2140 000039DD 8ED8                <1>         mov     ds, ax
  2141 000039DF 8EC0                <1>         mov     es, ax
  2142 000039E1 8EE0                <1>         mov     fs, ax
  2143 000039E3 8EE8                <1>         mov     gs, ax
  2144 000039E5 A1[886F0000]        <1> 	mov	eax, [k_page_dir]
  2145 000039EA 0F22D8              <1> 	mov	cr3, eax
  2146 000039ED 58                  <1> 	pop	eax ; 01/07/2015
  2147                              <1> 	; 19/10/2015
  2148 000039EE FC                  <1> 	cld
  2149                              <1> 	;
  2150 000039EF FE05[9E740000]      <1> 	inc	byte [sysflg]
  2151                              <1> 		; incb sysflg / indicate a system routine is in progress
  2152 000039F5 FB                  <1>         sti 	; 18/01/2014
  2153                              <1> 	;jnz	panic ; 24/05/2013
  2154                              <1> 	; 04/12/2021
  2155 000039F6 7405                <1> 	jz	short _1
  2156 000039F8 E979F9FFFF          <1> 	jmp	panic
  2157                              <1> 		; beq 1f
  2158                              <1> 		; jmp panic ; / called if trap inside system
  2159                              <1> ;1:
  2160                              <1> _1:	; 04/12/2021
  2161                              <1> 	; 16/04/2015
  2162 000039FD A3[A8740000]        <1> 	mov	[u.r0], eax
  2163 00003A02 8925[A4740000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2164                              <1> 	;
  2165                              <1> 		; mov $s.syst+2,clockp
  2166                              <1> 		; mov r0,-(sp) / save user registers 
  2167                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2168                              <1> 			   ; / in u.r0
  2169                              <1> 		; mov r1,-(sp)
  2170                              <1> 		; mov r2,-(sp)
  2171                              <1> 		; mov r3,-(sp)
  2172                              <1> 		; mov r4,-(sp)
  2173                              <1> 		; mov r5,-(sp)
  2174                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2175                              <1> 		             ; / arithmetic unit
  2176                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2177                              <1> 		             ; / extended arithmetic unit
  2178                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2179                              <1> 		             ; / arithmetic unit
  2180                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2181                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2182                              <1> 		; mov -(r0),r0 / sys inst in r0 10400xxx
  2183                              <1> 		; sub $sys,r0 / get xxx code
  2184 00003A08 C1E002              <1> 	shl	eax, 2
  2185                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2186 00003A0B 3DA0000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2187                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2188                              <1> 	;jnb	short badsys
  2189                              <1> 		; bhis badsys / yes, bad system call
  2190                              <1> 	; 25/12/2021
  2191 00003A10 7205                <1> 	jb	short _2
  2192 00003A12 E969010000          <1> 	jmp	badsys
  2193                              <1> _2:
  2194                              <1> 	; 25/12/2021
  2195                              <1> 	;cmc
  2196                              <1> 	;pushf	
  2197                              <1> 	;push	eax
  2198 00003A17 8B2D[A0740000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2199                              <1> 	;mov	al, 0FEh ; 11111110b
  2200                              <1> 	;;adc	al, 0 ; al = al + cf
  2201                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2202 00003A1D 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2203                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2204                              <1> 				 ; / and clear carry bit
  2205                              <1> 	;pop	ebp ; eax
  2206 00003A21 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2207                              <1> 	;popf
  2208                              <1>         ;;jc	badsys
  2209                              <1> 	;; 04/12/2021
  2210                              <1> 	;jnc	short _3
  2211                              <1> 	;jmp	badsys
  2212                              <1> ;_3:
  2213 00003A23 A1[A8740000]        <1> 	mov	eax, [u.r0]
  2214                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2215 00003A28 FFA5[2E3A0000]      <1> 	jmp	dword [ebp+syscalls]
  2216                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2217                              <1> 		            ; / to proper system routine.
  2218                              <1> 
  2219                              <1> 	; 09/01/2022
  2220                              <1> 	; 01/01/2022 (/etc/init error, BugFix efforts, test)
  2221                              <1> syscalls: ; 1:
  2222                              <1> 	; 21/09/2015
  2223                              <1> 	; 01/07/2015
  2224                              <1> 	; 16/04/2015 (32 bit address modification) 
  2225 00003A2E [4A3B0000]          <1> 	dd sysrele	; / 0
  2226 00003A32 [F23B0000]          <1> 	dd sysexit 	; / 1
  2227 00003A36 [1D3D0000]          <1> 	dd sysfork 	; / 2
  2228 00003A3A [233E0000]          <1> 	dd sysread 	; / 3
  2229 00003A3E [383E0000]          <1> 	dd syswrite 	; / 4
  2230 00003A42 [9B3E0000]          <1> 	dd sysopen 	; / 5
  2231 00003A46 [983F0000]          <1> 	dd sysclose 	; / 6
  2232 00003A4A [983C0000]          <1> 	dd syswait 	; / 7
  2233 00003A4E [333F0000]          <1> 	dd syscreat 	; / 8
  2234 00003A52 [2B430000]          <1> 	dd syslink 	; / 9
  2235 00003A56 [B9430000]          <1> 	dd sysunlink 	; / 10
  2236 00003A5A [C1440000]          <1> 	dd sysexec 	; / 11
  2237 00003A5E [DC4A0000]          <1> 	dd syschdir 	; / 12
  2238 00003A62 [F04B0000]          <1> 	dd systime 	; / 13
  2239 00003A66 [693F0000]          <1> 	dd sysmkdir 	; / 14
  2240 00003A6A [1B4B0000]          <1> 	dd syschmod 	; / 15
  2241 00003A6E [4A4B0000]          <1> 	dd syschown 	; / 16
  2242 00003A72 [244C0000]          <1> 	dd sysbreak 	; / 17
  2243 00003A76 [61480000]          <1> 	dd sysstat 	; / 18
  2244 00003A7A [274D0000]          <1> 	dd sysseek 	; / 19
  2245 00003A7E [394D0000]          <1> 	dd systell 	; / 20
  2246 00003A82 [4C5C0000]          <1> 	dd sysmount 	; / 21
  2247 00003A86 [265D0000]          <1> 	dd sysumount 	; / 22
  2248 00003A8A [AC4D0000]          <1> 	dd syssetuid 	; / 23
  2249 00003A8E [E14D0000]          <1> 	dd sysgetuid 	; / 24
  2250 00003A92 [FF4B0000]          <1> 	dd sysstime 	; / 25
  2251 00003A96 [A04D0000]          <1> 	dd sysquit 	; / 26
  2252 00003A9A [944D0000]          <1> 	dd sysintr 	; / 27
  2253 00003A9E [48480000]          <1> 	dd sysfstat 	; / 28
  2254 00003AA2 [B33F0000]          <1> 	dd sysemt 	; / 29
  2255 00003AA6 [E13F0000]          <1> 	dd sysmdate 	; / 30
  2256 00003AAA [38400000]          <1> 	dd sysstty 	; / 31
  2257 00003AAE [1E420000]          <1> 	dd sysgtty 	; / 32
  2258 00003AB2 [DC3F0000]          <1> 	dd sysilgins 	; / 33
  2259 00003AB6 [A2650000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2260                              <1> 			     ; 11/06/2014
  2261 00003ABA [CF650000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2262                              <1> 			     ; 01/07/2015
  2263 00003ABE [A7660000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2264                              <1> 			     ; 21/09/2015 - get last error number
  2265                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  2266                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  2267 00003AC2 [F14D0000]          <1> 	dd syssetgid	; 37
  2268 00003AC6 [144E0000]          <1> 	dd sysgetgid	; 38
  2269                              <1> 	; 18/06/2021 - Retro UNIX 386 v2 (ref: TRDOS 386 v2)
  2270 00003ACA [2C4E0000]          <1> 	dd sysver	; 39 ; (get) Retro Unix 386 version
  2271                              <1> 
  2272                              <1> end_of_syscalls:
  2273                              <1> 
  2274                              <1> error:
  2275                              <1> 	; 11/12/2021 (Retro UNIX 386 v1.2)
  2276                              <1> 	; 17/09/2015
  2277                              <1> 	; 03/09/2015
  2278                              <1> 	; 01/09/2015
  2279                              <1> 	; 09/06/2015
  2280                              <1> 	; 13/05/2015
  2281                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2282                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2283                              <1> 	;
  2284                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2285                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2286                              <1> 	;
  2287                              <1> 	; INPUTS -> none
  2288                              <1> 	; OUTPUTS ->
  2289                              <1> 	;	processor status - carry (c) bit is set (means error)
  2290                              <1> 	;
  2291                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2292                              <1> 	; 	      Because, jumps to error procedure
  2293                              <1> 	;	      disrupts push-pop nesting balance)
  2294                              <1> 	;
  2295 00003ACE 8B2D[A0740000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2296 00003AD4 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2297                              <1> 				 ; (system call will return with cf = 1)
  2298                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2299                              <1> 		               ; / users stack
  2300                              <1> 	; 17/09/2015
  2301 00003AD8 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2302                              <1> 				 ; for saving/restoring user registers	
  2303                              <1> 	;cmp	ebp, [u.usp]
  2304                              <1> 	;je	short err0	
  2305 00003ADB 892D[A4740000]      <1> 	mov	[u.usp], ebp
  2306                              <1> ;err0:
  2307                              <1> 	; 01/09/2015
  2308 00003AE1 8B25[A4740000]      <1> 	mov	esp, [u.usp]	; Retro Unix 8086 v1 modification!
  2309                              <1> 				; 10/04/2013
  2310                              <1> 				; (If an I/O error occurs during disk I/O,
  2311                              <1> 				; related procedures will jump to 'error'
  2312                              <1> 				; procedure directly without returning to 
  2313                              <1> 				; the caller procedure. So, stack pointer
  2314                              <1> 				; must be restored here.)
  2315                              <1> 	; 13/05/2015
  2316                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2317                              <1> 	;	'get last error' system call later. 	
  2318                              <1> 
  2319                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2320 00003AE7 C605[1A750000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2321                              <1> 
  2322                              <1> sysret: ; < return from system call>
  2323                              <1> 	; 11/12/2021
  2324                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2325                              <1> 	; 30/11/2021
  2326                              <1> 	; 10/09/2015
  2327                              <1> 	; 29/07/2015
  2328                              <1> 	; 25/06/2015
  2329                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2330                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2331                              <1> 	;
  2332                              <1> 	; 'sysret' first checks to see if process is about to be 
  2333                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2334                              <1> 	; If not, following happens:	 
  2335                              <1> 	; 	1) The user's stack pointer is restored.
  2336                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2337                              <1> 	;	   i-node has been modified. If it has, it is written out
  2338                              <1> 	;	   via 'ppoke'.
  2339                              <1> 	;	3) If the super block has been modified, it is written out
  2340                              <1> 	;	   via 'ppoke'.				
  2341                              <1> 	;	4) If the dismountable file system's super block has been
  2342                              <1> 	;	   modified, it is written out to the specified device
  2343                              <1> 	;	   via 'ppoke'.
  2344                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2345                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2346                              <1> 	;	   another user a chance to run.
  2347                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2348                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2349                              <1> 	;
  2350                              <1> 	; Calling sequence:
  2351                              <1> 	;	jump table or 'br sysret'
  2352                              <1> 	; Arguments: 
  2353                              <1> 	;	-	
  2354                              <1> 	; ...............................................................
  2355                              <1> 	;	
  2356                              <1> 	; ((AX=r1 for 'iget' input))
  2357                              <1> 	;	
  2358                              <1> 	;xor	ax, ax ; 04/05/2013
  2359                              <1> 	; 30/11/2021
  2360 00003AEE 31C0                <1> 	xor	eax, eax
  2361                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2362 00003AF0 FEC0                <1> 	inc	al ; 04/05/2013
  2363 00003AF2 3805[F8740000]      <1> 	cmp	[u.bsys], al ; 1
  2364                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2365                              <1> 	;jnb	sysexit ; 04/05/2013
  2366                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2367                              <1> 	; 04/12/2021
  2368 00003AF8 720F                <1> 	jb	short _3
  2369                              <1> 	; 11/12/2021
  2370 00003AFA C705[1C750000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2370 00003B02 0000                <1>
  2371 00003B04 E9E9000000          <1> 	jmp	sysexit
  2372                              <1> _3:
  2373                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2374                              <1> 		; mov u.sp,sp / no point stack to users stack
  2375 00003B09 FEC8                <1> 	dec 	al ; mov ax, 0
  2376                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2377 00003B0B E8F4180000          <1> 	call	iget
  2378                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2379                              <1> 		            ; / it is written out
  2380                              <1> 	;xor 	ax, ax ; 0
  2381                              <1> 	; 30/11/2021
  2382 00003B10 31C0                <1> 	xor	eax, eax
  2383 00003B12 3805[9C740000]      <1> 	cmp	[smod], al ; 0
  2384                              <1> 		; tstb	smod / has the super block been modified
  2385 00003B18 7614                <1> 	jna	short sysret1
  2386                              <1> 		; beq	1f / no, 1f
  2387 00003B1A A2[9C740000]        <1> 	mov	[smod], al ; 0
  2388                              <1> 		; clrb smod / yes, clear smod
  2389 00003B1F BB[4C750000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2390 00003B24 66810B0002          <1>    	or	word [ebx], 200h ;;
  2391                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2392                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2393                              <1> 		      	      ; / output
  2394                              <1> 	; AX = 0
  2395 00003B29 E89C260000          <1> 	call 	poke ; 07/08/2013
  2396                              <1> 	;call	ppoke
  2397                              <1> 	; AX = 0
  2398                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2399                              <1> sysret1: ;1:
  2400 00003B2E 3805[9D740000]      <1> 	cmp	[mmod], al ; 0
  2401                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2402                              <1> 		           ; / system
  2403 00003B34 7614                <1> 	jna	short sysrel0
  2404                              <1> 		; beq 1f / been modified?  no, 1f
  2405 00003B36 A2[9D740000]        <1> 	mov	[mmod], al ; 0	
  2406                              <1> 		; clrb	mmod / yes, clear mmod
  2407                              <1>         ;mov    ax, [mntd]
  2408                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2409 00003B3B BB[54770000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2410                              <1>         ;;mov	[ebx], al
  2411                              <1> 	;mov    [sb1], al
  2412                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2413 00003B40 66810B0002          <1> 	or	word [ebx], 200h
  2414                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2415                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2416 00003B45 E880260000          <1> 	call	poke ; 07/08/2013
  2417                              <1> 	;call	ppoke 
  2418                              <1> 		; jsr r0,ppoke / write it out to its device
  2419                              <1>         ;xor    al, al ; 26/04/2013       
  2420                              <1> ;1:
  2421                              <1> 		; tstb uquant / is the time quantum 0?
  2422                              <1> 		; bne 1f / no, don't swap it out
  2423                              <1> 
  2424                              <1> sysrele: ; < release >
  2425                              <1> 	; 14/10/2015
  2426                              <1> 	; 01/09/2015
  2427                              <1> 	; 24/07/2015
  2428                              <1> 	; 14/05/2015
  2429                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2430                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2431                              <1> 	;
  2432                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2433                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2434                              <1> 	; turns off the system flag. It then checked to see if there is
  2435                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2436                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2437                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2438                              <1> 	; the user, a rti is made.
  2439                              <1> 	;
  2440                              <1> 	; Calling sequence:
  2441                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2442                              <1> 	; Arguments:
  2443                              <1> 	;	-	
  2444                              <1> 	; ...............................................................
  2445                              <1> 	;	
  2446                              <1> 	; 23/02/2014 (swapret)
  2447                              <1> 	; 22/09/2013
  2448                              <1> sysrel0: ;1:
  2449 00003B4A 803D[F0740000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2450                              <1> 		; tstb uquant / is the time quantum 0?
  2451 00003B51 7705                <1>         ja      short swapret
  2452                              <1> 		; bne 1f / no, don't swap it out
  2453                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2454 00003B53 E81B130000          <1> 	call	tswap
  2455                              <1> 		; jsr r0,tswap / yes, swap it out
  2456                              <1> ;
  2457                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2458                              <1> swapret: ;1:
  2459                              <1> 	; 10/09/2015
  2460                              <1> 	; 01/09/2015
  2461                              <1> 	; 14/05/2015
  2462                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2463                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2464                              <1> 	; cli
  2465                              <1> 	; 24/07/2015
  2466                              <1> 	;
  2467                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2468                              <1> 	;; mov	esp, [u.usp]
  2469                              <1> 
  2470                              <1> 	; 22/09/2013
  2471 00003B58 E8FB140000          <1> 	call	isintr
  2472                              <1> 	; 20/10/2013
  2473 00003B5D 7405                <1> 	jz	short sysrel1
  2474 00003B5F E877000000          <1> 	call	intract
  2475                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2476                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2477                              <1> 		               ; / action
  2478                              <1> sysrel1:
  2479 00003B64 FA                  <1> 	cli ; 14/10/2015
  2480 00003B65 FE0D[9E740000]      <1> 	dec	byte [sysflg]
  2481                              <1> 		; decb sysflg / turn system flag off
  2482 00003B6B A1[08750000]        <1> 	mov     eax, [u.pgdir]
  2483 00003B70 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2484                              <1> 			  ; (others are different than kernel page tables) 
  2485                              <1> 	; 10/09/2015
  2486 00003B73 61                  <1> 	popad ; edi, esi, ebp, temp (increment esp by 4), ebx, edx, ecx, eax
  2487                              <1> 		; mov (sp)+,sc / restore user registers
  2488                              <1> 		; mov (sp)+,mq
  2489                              <1> 		; mov (sp)+,ac
  2490                              <1> 		; mov (sp)+,r5
  2491                              <1> 		; mov (sp)+,r4
  2492                              <1> 		; mov (sp)+,r3
  2493                              <1> 		; mov (sp)+,r2
  2494                              <1> 	;
  2495 00003B74 A1[A8740000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2496 00003B79 0FA9                <1> 	pop	gs
  2497 00003B7B 0FA1                <1> 	pop	fs
  2498 00003B7D 07                  <1> 	pop	es
  2499 00003B7E 1F                  <1> 	pop	ds
  2500 00003B7F CF                  <1> 	iretd	
  2501                              <1> 		; rti / no, return from interrupt
  2502                              <1> 
  2503                              <1> badsys:
  2504                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2505                              <1> 	; (Major Modification: 'core' dumping procedure in
  2506                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2507                              <1> 	;	has been changed to print 'Invalid System Call !'
  2508                              <1> 	;	message on the user's console tty.)
  2509                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2510                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2511                              <1> 	; (EAX = Function number)  
  2512                              <1> 	;
  2513 00003B80 FE05[F8740000]      <1> 	inc	byte [u.bsys]
  2514                              <1> 	;
  2515 00003B86 8B1D[A0740000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2516 00003B8C 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2517 00003B8E E855DBFFFF          <1> 	call	dwordtohex
  2518 00003B93 8915[E46C0000]      <1> 	mov	[bsys_msg_eip], edx
  2519 00003B99 A3[E86C0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2520 00003B9E A1[A8740000]        <1> 	mov	eax, [u.r0]
  2521 00003BA3 E840DBFFFF          <1> 	call	dwordtohex
  2522 00003BA8 8915[D46C0000]      <1> 	mov	[bsys_msg_eax], edx
  2523 00003BAE A3[D86C0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2524                              <1> 	; 11/12/2021
  2525                              <1> 	;xor	eax, eax
  2526                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2527                              <1> 	;mov	ebx, [u.fofp]
  2528                              <1> 	;mov	[ebx], eax
  2529                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2530                              <1> 	;inc	eax
  2531                              <1> 	; 11/12/2021 - Retro UNIX 386 v2 fs compatibility 
  2532                              <1> 	; (Retro UNIX 386 v1.2)
  2533                              <1> 	;mov	al, 8 ; /dev/tty inode number (runix v2 fs)
  2534                              <1> 	;; eax = 8 ; inode number of console tty (for user)	
  2535                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2536                              <1> 		; writei
  2537                              <1> 		; INPUTS ->
  2538                              <1> 		;    r1 - inode number
  2539                              <1> 		;    u.count - byte count to be written
  2540                              <1> 		;    u.base - points to user buffer
  2541                              <1> 		;    u.fofp - points to word with current file offset
  2542                              <1> 		; OUTPUTS ->
  2543                              <1> 		;    u.count - cleared
  2544                              <1> 		;    u.nread - accumulates total bytes passed back	
  2545                              <1> 		;
  2546                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2547                              <1> 	;call	writei
  2548                              <1> 	;;mov	eax, 1
  2549                              <1> 	;jmp	sysexit
  2550                              <1> 
  2551                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2552 00003BB3 BE[B56C0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2553 00003BB8 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2554 00003BBF 8A83[C3700000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2555 00003BC5 C605[B76F0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2556 00003BCC A2[DD740000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2557 00003BD1 E8B62A0000          <1> 	call	print_cmsg
  2558                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2559 00003BD6 E9F3FEFFFF          <1> 	jmp	error
  2560                              <1> 
  2561                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2562                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2563                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2564                              <1> 		; br 1f / error
  2565                              <1> 		; neg r1 / negate the i-number to open the core image file
  2566                              <1> 		       ; / for writing
  2567                              <1> 		; jsr r0,iopen / open the core image file
  2568                              <1> 		; jsr r0,itrunc / free all associated blocks
  2569                              <1> 		; br 2f
  2570                              <1> ;1:
  2571                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2572                              <1> 		; jsr r0,maknod / make an i-node
  2573                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2574                              <1> ;2:
  2575                              <1> 		; mov $core,u.base / move address core to u.base
  2576                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2577                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2578                              <1> 		; clr u.off / clear user offset
  2579                              <1> 		; jsr r0,writei / write out the core image to the user
  2580                              <1> 		; mov $user,u.base / pt. u.base to user
  2581                              <1> 		; mov $64.,u.count / u.count = 64
  2582                              <1> 		; jsr r0,writei / write out all the user parameters
  2583                              <1> 		; neg r1 / make i-number positive
  2584                              <1> 		; jsr r0,iclose / close the core image file
  2585                              <1> 		; br sysexit /
  2586                              <1> ;3:
  2587                              <1> 		; <core\0\0>
  2588                              <1> 
  2589                              <1> intract: ; / interrupt action
  2590                              <1> 	; 14/10/2015
  2591                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2592                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2593                              <1> 	;
  2594                              <1> 	; Retro UNIX 8086 v1 modification !
  2595                              <1> 	; (Process/task switching and quit routine by using
  2596                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2597                              <1> 	;
  2598                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2599                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2600                              <1> 	;		'intract' will jump to 'sysexit'.
  2601                              <1> 	;	    Intract will return to the caller 
  2602                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2603                              <1> 	; 14/10/2015
  2604 00003BDB FB                  <1> 	sti
  2605                              <1> 	; 07/12/2013	
  2606 00003BDC 66FF05[F6740000]    <1> 	inc 	word [u.quit]
  2607 00003BE3 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2608 00003BE5 66FF0D[F6740000]    <1> 	dec	word [u.quit]
  2609                              <1> 	; 16/04/2015
  2610 00003BEC C3                  <1> 	retn
  2611                              <1> intrct0:	
  2612 00003BED 58                  <1> 	pop	eax ; call intract -> retn
  2613                              <1> 	;
  2614 00003BEE 31C0                <1> 	xor 	eax, eax
  2615 00003BF0 FEC0                <1> 	inc	al  ; mov ax, 1
  2616                              <1> ;;;
  2617                              <1> 	; UNIX v1 original 'intract' routine... 
  2618                              <1> 	; / interrupt action
  2619                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2620                              <1> 		; bne 1f / no, 1f
  2621                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2622                              <1> 	; 1: / now in user area
  2623                              <1> 		; mov r1,-(sp) / save r1
  2624                              <1> 		; mov u.ttyp,r1 
  2625                              <1> 			; / pointer to tty buffer in control-to r1
  2626                              <1> 		; cmpb 6(r1),$177
  2627                              <1> 			; / is the interrupt char equal to "del"
  2628                              <1> 		; beq 1f / yes, 1f
  2629                              <1> 		; clrb 6(r1) 
  2630                              <1> 		        ; / no, clear the byte 
  2631                              <1> 			; / (must be a quit character)
  2632                              <1> 		; mov (sp)+,r1 / restore r1
  2633                              <1> 		; clr u.quit / clear quit flag
  2634                              <1> 		; bis $20,2(sp) 
  2635                              <1> 		    	; / set trace for quit (sets t bit of 
  2636                              <1> 			; / ps-trace trap)
  2637                              <1> 		; rti   ;  / return from interrupt
  2638                              <1> 	; 1: / interrupt char = del
  2639                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2640                              <1> 			   ; / in the buffer
  2641                              <1> 		; mov (sp)+,r1 / restore r1
  2642                              <1> 		; cmp u.intr,$core / should control be 
  2643                              <1> 				; / transferred to loc core?
  2644                              <1> 		; blo 1f
  2645                              <1> 		; jmp *u.intr / user to do rti yes, 
  2646                              <1> 				; / transfer to loc core
  2647                              <1> 	; 1:
  2648                              <1> 		; sys 1 / exit
  2649                              <1> 
  2650                              <1> sysexit: ; <terminate process>
  2651                              <1> 	; 30/11/2021 - etro UNIX 386 v1.2
  2652                              <1> 	; 01/09/2015
  2653                              <1> 	; 31/08/2015
  2654                              <1> 	; 14/05/2015
  2655                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2656                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2657                              <1> 	;
  2658                              <1> 	; 'sysexit' terminates a process. First each file that
  2659                              <1> 	; the process has opened is closed by 'flose'. The process
  2660                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2661                              <1> 	; searched to find children of the dying process. If any of
  2662                              <1> 	; children are zombies (died by not waited for), they are
  2663                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2664                              <1> 	; dying process's parent. When the parent is found, it is
  2665                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2666                              <1> 	; one of these, the dying process just dies. If it is waiting
  2667                              <1> 	; for a child process to die, it notified that it doesn't 
  2668                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2669                              <1> 	; (waiting to active). It is awakened and put on runq by
  2670                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2671                              <1> 	; it will never be run again but stays around until a 'wait'
  2672                              <1> 	; is completed by it's parent process. If the parent is not
  2673                              <1> 	; found, process just dies. This means 'swap' is called with
  2674                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2675                              <1> 	; to write out the process and 'rswap' reads the new process
  2676                              <1> 	; over the one that dies..i.e., the dying process is 
  2677                              <1> 	; overwritten and destroyed.	
  2678                              <1>  	;
  2679                              <1> 	; Calling sequence:
  2680                              <1> 	;	sysexit or conditional branch.
  2681                              <1> 	; Arguments:
  2682                              <1> 	;	-	
  2683                              <1> 	; ...............................................................
  2684                              <1> 	;	
  2685                              <1> 	; Retro UNIX 8086 v1 modification: 
  2686                              <1> 	;       System call number (=1) is in EAX register.
  2687                              <1> 	;
  2688                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2689                              <1> 	;       registers depending of function details.
  2690                              <1> 	;
  2691                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2692                              <1> 	;
  2693                              <1> ; / terminate process
  2694                              <1> 	; AX = 1
  2695                              <1> 	;dec 	ax ; 0
  2696                              <1> 	; 30/11/2021
  2697 00003BF2 48                  <1> 	dec	eax ; 0
  2698 00003BF3 66A3[F4740000]      <1> 	mov	[u.intr], ax ; 0
  2699                              <1> 		; clr u.intr / clear interrupt control word
  2700                              <1> 		; clr r1 / clear r1
  2701                              <1> 	; AX = 0
  2702                              <1> sysexit_1: ; 1:
  2703                              <1> 	; AX = File descriptor
  2704                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2705                              <1> 		; / Search the whole list
  2706 00003BF9 E8F50C0000          <1> 	call	fclose
  2707                              <1> 		; jsr r0,fclose / close all files the process opened
  2708                              <1> 	;; ignore error return
  2709                              <1> 		; br .+2 / ignore error return
  2710                              <1> 	;inc	ax
  2711 00003BFE FEC0                <1> 	inc	al
  2712                              <1> 		; inc r1 / increment file descriptor
  2713                              <1> 	;cmp	ax, 10
  2714 00003C00 3C0A                <1> 	cmp	al, 10
  2715                              <1> 		; cmp r1,$10. / end of u.fp list?
  2716 00003C02 72F5                <1> 	jb	short sysexit_1
  2717                              <1> 		; blt 1b / no, go back
  2718 00003C04 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2719                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2720 00003C0B 88A3[F3700000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2721                              <1> 		; clrb p.stat-1(r1) / free the process
  2722                              <1> 	;shl	bx, 1
  2723 00003C11 D0E3                <1> 	shl	bl, 1
  2724                              <1> 		; asl r1 / use r1 for index into the below tables
  2725 00003C13 668B8B[82700000]    <1> 	mov	cx, [ebx+p.pid-2]
  2726                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2727 00003C1A 668B93[A2700000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2728                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2729                              <1> 	; xor 	bx, bx ; 0
  2730 00003C21 30DB                <1> 	xor	bl, bl ; 0
  2731                              <1> 		; clr r2
  2732 00003C23 31F6                <1> 	xor	esi, esi ; 0
  2733                              <1> 		; clr r5 / initialize reg
  2734                              <1> sysexit_2: ; 1:
  2735                              <1> 	        ; / find children of this dying process, 
  2736                              <1> 		; / if they are zombies, free them
  2737                              <1> 	;add	bx, 2
  2738 00003C25 80C302              <1> 	add	bl, 2
  2739                              <1> 		; add $2,r2 / search parent process table 
  2740                              <1> 		          ; / for dying process's name
  2741 00003C28 66398B[A2700000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2742                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2743 00003C2F 7513                <1> 	jne	short sysexit_4
  2744                              <1> 		; bne 3f / no
  2745                              <1> 	;shr	bx, 1
  2746 00003C31 D0EB                <1> 	shr	bl, 1
  2747                              <1> 		; asr r2 / yes, it is a parent
  2748 00003C33 80BB[F3700000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2749                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2750                              <1> 				     ; / dying process a zombie
  2751 00003C3A 7506                <1> 	jne	short sysexit_3 
  2752                              <1> 		; bne 2f / no
  2753 00003C3C 88A3[F3700000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2754                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2755                              <1> sysexit_3: ; 2:
  2756                              <1> 	;shr	bx, 1
  2757 00003C42 D0E3                <1> 	shl	bl, 1
  2758                              <1> 		; asl r2
  2759                              <1> sysexit_4: ; 3:
  2760                              <1> 		; / search the process name table 
  2761                              <1> 		; / for the dying process's parent
  2762 00003C44 663993[82700000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2763                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2764 00003C4B 7502                <1> 	jne	short sysexit_5
  2765                              <1> 		; bne 3f / no
  2766 00003C4D 89DE                <1> 	mov	esi, ebx
  2767                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2768                              <1> 		          ; / process # x2) in r5
  2769                              <1> sysexit_5: ; 3:
  2770                              <1> 	;cmp	bx, nproc + nproc
  2771 00003C4F 80FB20              <1> 	cmp	bl, nproc + nproc
  2772                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2773 00003C52 72D1                <1> 	jb	short sysexit_2
  2774                              <1> 		; blt 1b / no, go back
  2775                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2776 00003C54 21F6                <1> 	and	esi, esi ; r5=r1
  2777 00003C56 7431                <1> 	jz	short sysexit_6
  2778                              <1> 		; beq 2f / no parent has been found. 
  2779                              <1> 		       ; / The process just dies
  2780 00003C58 66D1EE              <1> 	shr	si, 1
  2781                              <1> 		; asr r1 / set up index to p.stat
  2782 00003C5B 8A86[F3700000]      <1> 	mov	al, [esi+p.stat-1]
  2783                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2784 00003C61 20C0                <1> 	and	al, al
  2785 00003C63 7424                <1> 	jz	short sysexit_6
  2786                              <1> 		; beq 2f / if its been freed, 2f
  2787 00003C65 3C03                <1> 	cmp	al, 3
  2788                              <1> 		; cmp r2,$3 / is parent a zombie?
  2789 00003C67 7420                <1> 	je	short sysexit_6
  2790                              <1> 		; beq 2f / yes, 2f
  2791                              <1> 	; BH = 0
  2792 00003C69 8A1D[F9740000]      <1> 	mov	bl, [u.uno]
  2793                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2794 00003C6F C683[F3700000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2795                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2796                              <1> 	; 05/02/2014
  2797 00003C76 3C01                <1> 	cmp	al, 1 ; SRUN
  2798 00003C78 740F                <1> 	je	short sysexit_6
  2799                              <1> 	;cmp	al, 2
  2800                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2801                              <1> 			  ; / this child to die
  2802                              <1> 	;jne	short sysexit_6	
  2803                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2804                              <1> 	; 05/02/2014
  2805                              <1> 	; p.stat = 2 --> waiting
  2806                              <1> 	; p.stat = 4 --> sleeping
  2807 00003C7A C686[F3700000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2808                              <1> 	;dec	byte [esi+p.stat-1]
  2809                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2810 00003C81 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2811                              <1> 	; 
  2812                              <1> 	;mov	ebx, runq + 4
  2813                              <1> 		; mov $runq+4,r2 / on the runq
  2814 00003C84 E8C1120000          <1> 	call	putlu
  2815                              <1> 		; jsr r0, putlu
  2816                              <1> sysexit_6: ; 2:
  2817                              <1> 	; 31/08/2015
  2818                              <1> 		; / the process dies
  2819 00003C89 C605[F9740000]00    <1> 	mov	byte [u.uno], 0
  2820                              <1> 		; clrb u.uno / put zero as the process number, 
  2821                              <1> 	           ; / so "swap" will
  2822 00003C90 E8E8110000          <1> 	call	swap
  2823                              <1> 		; jsr r0,swap / overwrite process with another process
  2824                              <1> hlt_sys:
  2825                              <1> 	;sti ; 18/01/2014
  2826                              <1> hlts0:
  2827 00003C95 F4                  <1> 	hlt
  2828 00003C96 EBFD                <1> 	jmp	short hlts0
  2829                              <1> 		; 0 / and thereby kill it; halt?
  2830                              <1> 
  2831                              <1> syswait: ; < wait for a processs to die >
  2832                              <1> 	; 09/02/2022
  2833                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2834                              <1> 	; 17/09/2015
  2835                              <1> 	; 02/09/2015
  2836                              <1> 	; 01/09/2015
  2837                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2838                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2839                              <1> 	;
  2840                              <1> 	; 'syswait' waits for a process die. 
  2841                              <1> 	; It works in following way:
  2842                              <1> 	;    1) From the parent process number, the parent's 
  2843                              <1> 	; 	process name is found. The p.ppid table of parent
  2844                              <1> 	;	names is then searched for this process name.
  2845                              <1> 	;	If a match occurs, r2 contains child's process
  2846                              <1> 	;	number. The child status is checked to see if it is
  2847                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2848                              <1> 	;	If it is, the child process is freed and it's name
  2849                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2850                              <1> 	;	If the child is not a zombie, nothing happens and
  2851                              <1> 	;	the search goes on through the p.ppid table until
  2852                              <1> 	;	all processes are checked or a zombie is found.
  2853                              <1> 	;    2) If no zombies are found, a check is made to see if
  2854                              <1> 	;	there are any children at all. If there are none,
  2855                              <1> 	;	an error return is made. If there are, the parent's
  2856                              <1> 	;	status is set to 2 (waiting for child to die),
  2857                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2858                              <1> 	;	is made to wait on the next process.
  2859                              <1> 	;
  2860                              <1> 	; Calling sequence:
  2861                              <1> 	;	?
  2862                              <1> 	; Arguments:
  2863                              <1> 	;	-
  2864                              <1> 	; Inputs: - 
  2865                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2866                              <1> 	; ...............................................................
  2867                              <1> 	;				
  2868                              <1> 	
  2869                              <1> ; / wait for a process to die
  2870                              <1> 
  2871                              <1> syswait_0:
  2872 00003C98 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2873                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2874 00003C9F D0E3                <1> 	shl	bl, 1
  2875                              <1> 	;shl	bx, 1
  2876                              <1> 		; asl r1 / x2 to get index into p.pid table
  2877 00003CA1 668B83[82700000]    <1> 	mov	ax, [ebx+p.pid-2]
  2878                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2879 00003CA8 31F6                <1> 	xor	esi, esi
  2880                              <1> 		; clr r2
  2881 00003CAA 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2882                              <1> 	;xor 	cl, cl
  2883                              <1> 		; clr r3 / initialize reg 3
  2884                              <1> syswait_1: ; 1:
  2885                              <1> 	; 09/02/2022
  2886 00003CAC 46                  <1> 	inc	esi
  2887 00003CAD 46                  <1> 	inc	esi
  2888                              <1> 	;add	si, 2
  2889                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2890                              <1> 			  ; / search table of parent processes 
  2891                              <1> 			  ; / for this process name
  2892 00003CAE 663B86[A2700000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2893                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2894                              <1> 			            ; / process number
  2895 00003CB5 7531                <1> 	jne	short syswait_3
  2896                              <1> 		; bne 3f / branch if no match of parent process name
  2897                              <1> 	;inc	cx
  2898 00003CB7 FEC1                <1> 	inc	cl
  2899                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2900                              <1> 	; 09/02/2022
  2901 00003CB9 D1EE                <1> 	shr	esi, 1
  2902                              <1> 	;shr	si, 1
  2903                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2904                              <1> 	; The possible states ('p.stat' values) of a process are:
  2905                              <1> 	;	0 = free or unused
  2906                              <1> 	;	1 = active
  2907                              <1> 	;	2 = waiting for a child process to die
  2908                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2909 00003CBB 80BE[F3700000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2910                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2911 00003CC2 7522                <1> 	jne	short syswait_2
  2912                              <1> 		; bne 2f / no, skip it
  2913 00003CC4 88BE[F3700000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2914                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2915                              <1> 	; 09/02/2022
  2916 00003CCA D1E6                <1> 	shl	esi, 1
  2917                              <1> 	;shl	si, 1
  2918                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2919 00003CCC 0FB786[82700000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2920 00003CD3 A3[A8740000]        <1> 	mov	[u.r0], eax
  2921                              <1> 		; mov p.pid-2(r2),*u.r0 
  2922                              <1> 			      ; / put childs process name in (u.r0)
  2923                              <1> 	;
  2924                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2925                              <1> 	;
  2926                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2927                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2928                              <1> 	; system call loop from the application/program if it calls
  2929                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2930                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2931                              <1> 	;
  2932                              <1> 	; Note: syswait will return with error if there is not a
  2933                              <1> 	;       zombie or running process to wait.	
  2934                              <1> 	;
  2935                              <1> 	;sub	ax, ax
  2936                              <1> 	; 08/01/2022
  2937 00003CD8 29C0                <1> 	sub	eax, eax
  2938 00003CDA 668986[A2700000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2939 00003CE1 E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2940                              <1> 	;
  2941                              <1> 	;jmp	sysret
  2942                              <1> 		; br sysret1 / return cause child is dead
  2943                              <1> syswait_2: ; 2:
  2944                              <1> 	; 09/02/2022
  2945 00003CE6 D1E6                <1> 	shl	esi, 1
  2946                              <1> 	;shl	si, 1
  2947                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2948                              <1> syswait_3: ; 3:
  2949 00003CE8 6683FE20            <1> 	cmp	si, nproc+nproc
  2950                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2951 00003CEC 72BE                <1> 	jb	short syswait_1
  2952                              <1> 		; blt 1b / no, continue search
  2953                              <1> 	;and	cx, cx
  2954 00003CEE 20C9                <1> 	and	cl, cl
  2955                              <1> 		; tst r3 / one gets here if there are no children 
  2956                              <1> 		       ; / or children that are still active
  2957                              <1> 	; 30/10/2013
  2958 00003CF0 7515                <1> 	jnz	short syswait_4
  2959                              <1> 	;jz	error
  2960                              <1> 		; beq error1 / there are no children, error
  2961 00003CF2 890D[A8740000]      <1> 	mov	[u.r0], ecx ; 0
  2962                              <1> 	; 09/02/2022
  2963 00003CF8 C705[1C750000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2963 00003D00 0000                <1>
  2964                              <1> 			; miscellaneous/other errors
  2965 00003D02 E9C7FDFFFF          <1> 	jmp	error
  2966                              <1> syswait_4:
  2967 00003D07 8A1D[F9740000]      <1> 	mov	bl, [u.uno]
  2968                              <1> 		; movb u.uno,r1 / there are children so put 
  2969                              <1> 			      ; / parent process number in r1
  2970 00003D0D FE83[F3700000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2971                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2972                              <1> 				  ; / other children to die
  2973                              <1> 	; 04/11/2013
  2974 00003D13 E865110000          <1> 	call	swap
  2975                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2976 00003D18 E97BFFFFFF          <1> 	jmp	syswait_0
  2977                              <1> 		; br syswait / wait on next process
  2978                              <1> 
  2979                              <1> sysfork: ; < create a new process >
  2980                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2981                              <1> 	; 18/09/2015
  2982                              <1> 	; 04/09/2015
  2983                              <1> 	; 02/09/2015
  2984                              <1> 	; 01/09/2015
  2985                              <1> 	; 28/08/2015
  2986                              <1> 	; 14/05/2015
  2987                              <1> 	; 10/05/2015
  2988                              <1> 	; 09/05/2015
  2989                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2990                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2991                              <1> 	;
  2992                              <1> 	; 'sysfork' creates a new process. This process is referred
  2993                              <1> 	; to as the child process. This new process core image is
  2994                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2995                              <1> 	; distinction is the return location and the fact that (u.r0)
  2996                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2997                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2998                              <1> 	; 'sysfork' works in the following manner: 	
  2999                              <1> 	;    1) The process status table (p.stat) is searched to find
  3000                              <1> 	;	a process number that is unused. If none are found
  3001                              <1> 	;	an error occurs.
  3002                              <1> 	;    2) when one is found, it becomes the child process number
  3003                              <1> 	;	and it's status (p.stat) is set to active.
  3004                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3005                              <1> 	;	character in that tty buffer is cleared.
  3006                              <1> 	;    4) The child process is put on the lowest priority run 
  3007                              <1> 	;	queue via 'putlu'.
  3008                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3009                              <1> 	;	it is a unique number) and is put in the child's unique
  3010                              <1> 	;	identifier; process id (p.pid).
  3011                              <1> 	;    6) The process name of the parent is then obtained and
  3012                              <1> 	;	placed in the unique identifier of the parent process
  3013                              <1> 	;	name is then put in 'u.r0'.	
  3014                              <1> 	;    7) The child process is then written out on disk by
  3015                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3016                              <1> 	;	and the child is born. (The child process is written 
  3017                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3018                              <1> 	;	number.)
  3019                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3020                              <1> 	;    9) The child process name is put in 'u.r0'.
  3021                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3022                              <1> 	;	create the return address for the parent process.
  3023                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3024                              <1> 	;	the parent has opened. For each file the parent has
  3025                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3026                              <1> 	;	to indicate that the child process also has opened
  3027                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3028                              <1> 	;
  3029                              <1> 	; Calling sequence:
  3030                              <1> 	;	from shell ?
  3031                              <1> 	; Arguments:
  3032                              <1> 	;	-
  3033                              <1> 	; Inputs: -
  3034                              <1> 	; Outputs: *u.r0 - child process name
  3035                              <1> 	; ...............................................................
  3036                              <1> 	;	
  3037                              <1> 	; Retro UNIX 8086 v1 modification: 
  3038                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3039                              <1> 	;	= process id of child a parent process returns
  3040                              <1> 	;	= process id of parent when a child process returns
  3041                              <1> 	;
  3042                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3043                              <1> 	;	in following manner: (with an example: c library, fork)
  3044                              <1> 	;	
  3045                              <1> 	;	1:
  3046                              <1> 	;		sys	fork
  3047                              <1> 	;			br 1f  / child process returns here
  3048                              <1> 	;		bes	2f     / parent process returns here
  3049                              <1> 	;		/ pid of new process in r0
  3050                              <1> 	;		rts	pc
  3051                              <1> 	;	2: / parent process condionally branches here
  3052                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3053                              <1> 	;		rts	pc
  3054                              <1> 	;
  3055                              <1> 	;	1: / child process brances here
  3056                              <1> 	;		clr	r0   / pid = 0 in child process
  3057                              <1> 	;		rts	pc
  3058                              <1> 	;
  3059                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3060                              <1> 	;		// pid = fork();
  3061                              <1> 	;		//
  3062                              <1> 	;		// pid == 0 in child process; 
  3063                              <1> 	;		// pid == -1 means error return
  3064                              <1> 	;		// in child, 
  3065                              <1> 	;		//	parents id is in par_uid if needed
  3066                              <1> 	;		
  3067                              <1> 	;		_fork:
  3068                              <1> 	;			mov	$.fork,eax
  3069                              <1> 	;			int	$0x30
  3070                              <1> 	;			jmp	1f
  3071                              <1> 	;			jnc	2f
  3072                              <1> 	;			jmp	cerror
  3073                              <1> 	;		1:
  3074                              <1> 	;			mov	eax,_par_uid
  3075                              <1> 	;			xor	eax,eax
  3076                              <1> 	;		2:
  3077                              <1> 	;			ret
  3078                              <1> 	;
  3079                              <1> 	;	In Retro UNIX 8086 v1,
  3080                              <1> 	;	'sysfork' returns in following manner:
  3081                              <1> 	;	
  3082                              <1> 	;		mov	ax, sys_fork
  3083                              <1> 	;		mov	bx, offset @f ; routine for child
  3084                              <1> 	;		int	20h
  3085                              <1> 	;		jc	error
  3086                              <1> 	;		
  3087                              <1> 	;	; Routine for parent process here (just after 'jc')
  3088                              <1> 	;		mov	word ptr [pid_of_child], ax
  3089                              <1> 	;		jmp	next_routine_for_parent	
  3090                              <1> 	;
  3091                              <1> 	;	@@: ; routine for child process here				
  3092                              <1> 	;		....	
  3093                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3094                              <1> 	;	       for child process by using BX input.
  3095                              <1> 	;	      (at first, parent process will return then 
  3096                              <1> 	;	      child process will return -after swapped in-
  3097                              <1> 	;	      'syswait' is needed in parent process
  3098                              <1> 	;	      if return from child process will be waited for.)
  3099                              <1> 	;	  				
  3100                              <1> 	
  3101                              <1> ; / create a new process
  3102                              <1> 	; EBX = return address for child process 
  3103                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3104 00003D1D 31F6                <1> 	xor 	esi, esi
  3105                              <1> 		; clr r1
  3106                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3107 00003D1F 46                  <1> 	inc	esi
  3108                              <1> 		; inc r1
  3109 00003D20 80BE[F3700000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3110                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3111 00003D27 760B                <1> 	jna	short sysfork_2	
  3112                              <1> 		; beq 1f / it's unused so branch
  3113 00003D29 6683FE10            <1> 	cmp	si, nproc
  3114                              <1> 		; cmp r1,$nproc / all processes checked
  3115 00003D2D 72F0                <1> 	jb	short sysfork_1
  3116                              <1> 		; blt 1b / no, branch back
  3117                              <1> 	;
  3118                              <1> 	; Retro UNIX 8086 v1. modification:
  3119                              <1> 	;	Parent process returns from 'sysfork' to address 
  3120                              <1> 	;	which is just after 'sysfork' system call in parent
  3121                              <1> 	;	process. Child process returns to address which is put
  3122                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3123                              <1> 	;
  3124                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3125                              <1> 		             ; / to old process return
  3126                              <1> 		; br error1 / no room for a new process
  3127                              <1> sysfork_0:
  3128 00003D2F E99AFDFFFF          <1> 	jmp	error
  3129                              <1> sysfork_2: ; 1:
  3130 00003D34 E86DF0FFFF          <1> 	call	allocate_page
  3131                              <1> 	;jc	error
  3132                              <1> 	; 08/01/2022
  3133 00003D39 72F4                <1> 	jc	short sysfork_0
  3134                              <1> 
  3135 00003D3B 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3136                              <1> 	; Retro UNIX 386 v1 modification!
  3137 00003D3C E85EF2FFFF          <1> 	call	duplicate_page_dir
  3138                              <1> 		; EAX = New page directory 
  3139 00003D41 7308                <1> 	jnc	short sysfork_3
  3140 00003D43 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3141 00003D44 E825F2FFFF          <1> 	call 	deallocate_page
  3142                              <1> 	;jmp	error
  3143                              <1> 	; 08/01/2022
  3144 00003D49 EBE4                <1> 	jmp	short sysfork_0  ; error
  3145                              <1> sysfork_3:
  3146                              <1> 	; Retro UNIX 386 v1 modification !
  3147 00003D4B 56                  <1> 	push	esi
  3148 00003D4C E8A3110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3149                              <1> 		      ; and interrupt return components (for IRET)
  3150 00003D51 8705[08750000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3151 00003D57 A3[0C750000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3152 00003D5C 5E                  <1> 	pop	esi
  3153 00003D5D 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3154                              <1> 		; [u.usp] = esp
  3155 00003D5E 89F7                <1> 	mov	edi, esi
  3156                              <1> 	;shl	di, 2
  3157                              <1> 	; 08/01/2022
  3158 00003D60 C1E702              <1> 	shl	edi, 2
  3159 00003D63 8987[00710000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3160 00003D69 A3[04750000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3161                              <1> 	; 28/08/2015
  3162 00003D6E 0FB605[F9740000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3163                              <1> 		; movb u.uno,-(sp) / save parent process number
  3164 00003D75 89C7                <1> 	mov	edi, eax
  3165 00003D77 50                  <1>         push	eax ; ** 
  3166 00003D78 8A87[C3700000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3167                              <1> 	; 18/09/2015
  3168                              <1> 	;mov	[esi+p.ttyc-1], al ; set child's console tty
  3169                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3170 00003D7E 668986[C3700000]    <1> 	mov     [esi+p.ttyc-1], ax ; al - set child's console tty
  3171                              <1> 				   ; ah - reset child's wait channel	
  3172 00003D85 89F0                <1> 	mov	eax, esi
  3173 00003D87 A2[F9740000]        <1> 	mov	[u.uno], al ; child process number
  3174                              <1> 		;movb r1,u.uno / set child process number to r1
  3175 00003D8C FE86[F3700000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3176                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3177                              <1> 				; / process to active status
  3178                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3179                              <1> 			      ; / control tty buffer in r2
  3180                              <1>                 ; beq 2f / branch, if no such tty assigned
  3181                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3182                              <1> 	; 2:
  3183 00003D92 53                  <1> 	push	ebx  ; * return address for the child process
  3184                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3185                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3186                              <1> 		; mov $runq+4,r2
  3187 00003D93 E8B2110000          <1> 	call	putlu 
  3188                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3189                              <1> 			   ; / run queue
  3190                              <1> 	; 08/01/2022
  3191 00003D98 D1E6                <1> 	shl	esi, 1
  3192                              <1> 	;shl	si, 1
  3193                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3194                              <1> 		       ; / into p.pid table
  3195 00003D9A 66FF05[8E740000]    <1> 	inc	word [mpid]
  3196                              <1> 		; inc mpid / increment m.pid; get a new process name
  3197 00003DA1 66A1[8E740000]      <1> 	mov	ax, [mpid]
  3198 00003DA7 668986[82700000]    <1> 	mov	[esi+p.pid-2], ax
  3199                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3200                              <1> 				    ; / in child process' name slot
  3201 00003DAE 5A                  <1> 	pop	edx  ; * return address for the child process
  3202                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3203 00003DAF 5B                  <1>   	pop	ebx  ; **
  3204                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3205                              <1> 		; movb (sp),r2 / put parent process number in r2
  3206                              <1> 	; 08/01/2022
  3207 00003DB0 D1E3                <1> 	shl	ebx, 1
  3208                              <1> 	;shl 	bx, 1
  3209                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3210                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3211 00003DB2 668B83[82700000]    <1> 	mov	ax, [ebx+p.pid-2]
  3212                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3213                              <1> 				   ; / process
  3214 00003DB9 668986[A2700000]    <1> 	mov	[esi+p.ppid-2], ax
  3215                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3216                              <1> 			  ; / in parent process slot for child
  3217 00003DC0 A3[A8740000]        <1> 	mov	[u.r0], eax	
  3218                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3219                              <1> 			     ; / at location where r0 was saved
  3220 00003DC5 8B2D[A0740000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3221 00003DCB 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3222                              <1> 			   ; * return address for the child process
  3223                              <1> 		; mov $sysret1,-(sp) /
  3224                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3225                              <1> 			      ; / user is swapped out
  3226                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3227                              <1> 	; 04/09/2015 - 01/09/2015
  3228                              <1> 	; [u.usp] = esp
  3229 00003DCE 68[EE3A0000]        <1> 	push	sysret ; ***
  3230 00003DD3 8925[A4740000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3231                              <1> 			     ; (for child process)	
  3232 00003DD9 31C0                <1> 	xor 	eax, eax
  3233 00003DDB 66A3[DE740000]      <1> 	mov 	[u.ttyp], ax ; 0
  3234                              <1> 	;
  3235 00003DE1 E80E110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3236                              <1> 		;jsr r0,wswap / put child process out on drum
  3237                              <1> 		;jsr r0,unpack / unpack user stack
  3238                              <1> 		;mov u.usp,sp / restore user stack pointer
  3239                              <1> 		; tst (sp)+ / bump stack pointer
  3240                              <1> 	; Retro UNIX 386 v1 modification !
  3241 00003DE6 58                  <1> 	pop	eax ; ***
  3242                              <1> 	; 08/01/2022
  3243 00003DE7 D1E3                <1> 	shl	ebx, 1
  3244                              <1> 	;shl 	bx, 1
  3245 00003DE9 8B83[00710000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3246 00003DEF E829110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3247                              <1> 		      ; registers and return address (for IRET)
  3248                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3249 00003DF4 0FB705[8E740000]    <1>         movzx   eax, word [mpid]
  3250 00003DFB A3[A8740000]        <1> 	mov	[u.r0], eax
  3251                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3252                              <1> 			       ; / where r0 was saved
  3253                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3254                              <1> 			          ; / process return
  3255                              <1> 	;xor	ebx, ebx
  3256 00003E00 31F6                <1> 	xor     esi, esi
  3257                              <1> 		;clr r1
  3258                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3259                              <1> 	      ; / opened by the parent process
  3260                              <1> 	; 08/01/2022
  3261                              <1> 	; 01/09/2015
  3262 00003E02 30FF                <1> 	xor	bh, bh
  3263 00003E04 8A9E[B2740000]      <1> 	mov 	bl, [esi+u.fp]
  3264                              <1> 	; 08/01/2022
  3265                              <1> 	;mov 	al, [esi+u.fp]
  3266                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3267 00003E0A 08DB                <1> 	or	bl, bl
  3268                              <1> 	; 08/01/2022
  3269                              <1> 	;or	al, al
  3270 00003E0C 7409                <1> 	jz	short sysfork_5	
  3271                              <1> 		; beq 2f / file has not been opened by parent, 
  3272                              <1> 		       ; / so branch
  3273                              <1> 	;mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3274                              <1> 	; 08/01/2022
  3275                              <1> 	;mov	ah, 16 ; Retro UNIX 386 v2 fsp structure size = 16 bytes
  3276                              <1> 	;mul	ah
  3277                              <1> 	;;movzx	ebx, ax
  3278                              <1> 	;mov	bx, ax
  3279                              <1> 	;mov	ebx, eax ; 08/01/2022
  3280                              <1> 	;shl	bx, 3
  3281                              <1> 		; asl r2 / multiply by 8
  3282                              <1>        		; asl r2 / to get index into fsp table
  3283                              <1>        		; asl r2
  3284                              <1> 	; 08/01/2022
  3285 00003E0E C1E304              <1> 	shl	ebx, 4 ; multiply by 16
  3286                              <1> 	; 08/01/2022
  3287 00003E11 FE83[3A710000]      <1> 	inc	byte [ebx+fsp-10] ; Retro UNIX 386 v2 fs fsp structure
  3288                              <1>   	;inc	byte [ebx+fsp-2]
  3289                              <1> 		; incb fsp-2(r2) / increment number of processes
  3290                              <1> 			     ; / using file, because child will now be
  3291                              <1> 			     ; / using this file
  3292                              <1> sysfork_5: ; 2:
  3293 00003E17 46                  <1>         inc     esi
  3294                              <1> 		; inc r1 / get next open file
  3295 00003E18 6683FE0A            <1>         cmp     si, 10
  3296                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3297                              <1> 			  ; / can be opened
  3298 00003E1C 72E4                <1> 	jb	short sysfork_4	
  3299                              <1> 		; blt 1b / check next entry
  3300 00003E1E E9CBFCFFFF          <1> 	jmp	sysret
  3301                              <1> 		; br sysret1
  3302                              <1> 
  3303                              <1> sysread: ; < read from file >
  3304                              <1> 	; 24/12/2021
  3305                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3306                              <1> 	; 27/03/2020
  3307                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3308                              <1> 	; 13/05/2015
  3309                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3310                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3311                              <1> 	;
  3312                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3313                              <1> 	; characters to be read. If finds the file from the file
  3314                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3315                              <1> 	; is returned from a successful open call (sysopen).
  3316                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3317                              <1> 	; is read into core via 'readi'.
  3318                              <1> 	;
  3319                              <1> 	; Calling sequence:
  3320                              <1> 	;	sysread; buffer; nchars
  3321                              <1> 	; Arguments:
  3322                              <1> 	;	buffer - location of contiguous bytes where 
  3323                              <1> 	;		 input will be placed.
  3324                              <1> 	;	nchars - number of bytes or characters to be read.
  3325                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3326                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3327                              <1> 	; ...............................................................
  3328                              <1> 	;				
  3329                              <1> 	; Retro UNIX 8086 v1 modification: 
  3330                              <1> 	;       'sysread' system call has three arguments; so,
  3331                              <1> 	;	* 1st argument, file descriptor is in BX register
  3332                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3333                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3334                              <1> 	;
  3335                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3336                              <1> 	;	to the user with number of bytes read. 
  3337                              <1> 	;
  3338                              <1> 
  3339 00003E23 E839000000          <1> 	call	rw1
  3340                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3341                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3342                              <1>        	; 04/12/2021
  3343 00003E28 7209                <1> 	jc	short sysread_err
  3344 00003E2A 7529                <1> 	jnz	short rw3 ; error ! (permission denied)
  3345                              <1> 	;		; read a file while it is open for write!
  3346                              <1> 
  3347                              <1> 	; eax = inode number
  3348                              <1> 
  3349                              <1> 	; 04/12/2021
  3350                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3351                              <1> 	;test	ah, 80h
  3352                              <1> 	;	; tst r1 / negative i-number?
  3353                              <1> 	;;jnz	error
  3354                              <1> 	;;	; ble error1 / yes, error 1 to read
  3355                              <1> 	;;		   ; / it should be positive
  3356                              <1> 	;; 04/12/2021
  3357                              <1> 	;jnz	short sysread_err
  3358                              <1> 
  3359 00003E2C E84D190000          <1> 	call	readi
  3360                              <1> 		; jsr r0,readi / read data into core
  3361 00003E31 EB13                <1> 	jmp	short rw0
  3362                              <1> 		; br 1f
  3363                              <1> sysread_err:
  3364                              <1> syswrite_err:
  3365                              <1> 	; 04/12/2021
  3366 00003E33 E996FCFFFF          <1> 	jmp	error
  3367                              <1> 
  3368                              <1> syswrite: ; < write to file >
  3369                              <1> 	; 24/12/2021
  3370                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3371                              <1> 	; 27/03/2020
  3372                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3373                              <1> 	; 13/05/2015
  3374                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3375                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3376                              <1> 	;
  3377                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3378                              <1> 	; and the number of characters to write. If finds the file
  3379                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3380                              <1> 	; descriptor is returned from a successful open or create call
  3381                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3382                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3383                              <1> 	;
  3384                              <1> 	; Calling sequence:
  3385                              <1> 	;	syswrite; buffer; nchars
  3386                              <1> 	; Arguments:
  3387                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3388                              <1> 	;	nchars - number of characters to be written.
  3389                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3390                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3391                              <1> 	; ...............................................................
  3392                              <1> 	;				
  3393                              <1> 	; Retro UNIX 8086 v1 modification: 
  3394                              <1> 	;       'syswrite' system call has three arguments; so,
  3395                              <1> 	;	* 1st argument, file descriptor is in BX register
  3396                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3397                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3398                              <1> 	;
  3399                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3400                              <1> 	;	to the user with number of bytes written. 
  3401                              <1> 	;
  3402                              <1> 
  3403 00003E38 E824000000          <1> 	call	rw1
  3404                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3405                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3406                              <1>        	; 04/12/2021
  3407 00003E3D 72F4                <1> 	jc	short syswrite_err
  3408 00003E3F 7414                <1> 	jz	short rw3 ; error ! (permission denied)
  3409                              <1> 			; write to a file while it is open for read
  3410                              <1> 	; eax = inode number
  3411                              <1> 	
  3412                              <1> 	; 04/12/2021
  3413                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3414                              <1> 	;test	ah, 80h
  3415                              <1> 	;	; tst r1 / positive i-number ?
  3416                              <1>         ;jz	short rw3 ; 13/05/2015
  3417                              <1> 	;;jz	error
  3418                              <1> 	;	; bge error1 / yes, error 1 
  3419                              <1> 	;		   ; / negative i-number means write
  3420                              <1>         ;neg	ax
  3421                              <1> 	;	; neg r1 / make it positive
  3422                              <1> 	
  3423 00003E41 E8481B0000          <1> 	call	writei
  3424                              <1>         	; jsr r0,writei / write data
  3425                              <1> rw0: ; 1:
  3426 00003E46 A1[D4740000]        <1>         mov	eax, [u.nread]
  3427 00003E4B A3[A8740000]        <1> 	mov	[u.r0], eax
  3428                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3429                              <1> 				  ; / into (u.r0)
  3430 00003E50 E999FCFFFF          <1> 	jmp	sysret
  3431                              <1>         	; br sysret1
  3432                              <1> rw3: 
  3433                              <1> 	; 13/05/2015
  3434 00003E55 C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3434 00003E5D 0000                <1>
  3435                              <1> 	;stc
  3436                              <1> 	;retn
  3437                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.2
  3438 00003E5F EBD2                <1> 	jmp	short syswrite_err
  3439                              <1> 
  3440                              <1> rw1:	
  3441                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3442                              <1> 	; 27/03/2020
  3443                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3444                              <1> 	; 14/05/2015
  3445                              <1> 	; 13/05/2015
  3446                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3447                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3448                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3449                              <1> 	;
  3450                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3451                              <1> 				;(in the user's virtual memory space)
  3452                              <1> 	;mov	[u.count], edx 
  3453                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3454                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3455                              <1> 	;;mov	eax, ebx ; file descriptor
  3456                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3457                              <1> 		             ; / (index to u.fp table) in r1
  3458                              <1> 	; 13/05/2015
  3459 00003E61 C705[A8740000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3459 00003E69 0000                <1>
  3460                              <1> 	;
  3461                              <1> 	;; call	getf
  3462                              <1>         ; ebx = File descriptor
  3463 00003E6B E8C90A0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3464                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3465                              <1> 	; AX = I-number of the file ; negative i-number means write
  3466                              <1> 
  3467                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3468                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3469                              <1> 	; BL = open mode & status flag (0 = read, 1 = write)
  3470                              <1> 	; eax = inode number (ax)
  3471                              <1> 	; 27/03/2020
  3472                              <1> 	; [cdev] = logical drive number 	
  3473                              <1> 
  3474                              <1> 	; 13/05/2015
  3475 00003E70 6683F801            <1> 	cmp 	ax, 1
  3476 00003E74 721A                <1> 	jb	short rw2
  3477                              <1> 	;
  3478 00003E76 890D[CC740000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3479                              <1> 				;(in the user's virtual memory space)
  3480 00003E7C 8915[D0740000]      <1> 	mov	[u.count], edx 
  3481                              <1> 	; 14/05/2015
  3482 00003E82 C705[1C750000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3482 00003E8A 0000                <1>
  3483                              <1> 
  3484                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3485                              <1> 	; 27/03/2020 - Retro UNIX 386 v2
  3486 00003E8C 80E301              <1> 	and	bl, 1
  3487                              <1> 		; zf = 0 -> open for write	
  3488                              <1> 		; zf = 1 -> open for read
  3489 00003E8F C3                  <1> 	retn
  3490                              <1>         	; rts r0
  3491                              <1> rw2:
  3492                              <1> 	; 13/05/2015
  3493 00003E90 C705[1C750000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3493 00003E98 0000                <1>
  3494 00003E9A C3                  <1> 	retn
  3495                              <1> 
  3496                              <1> 	; 08/01/2022
  3497                              <1> 	; 02/01/2022
  3498                              <1> 	; 01/01/2022
  3499                              <1> 	; 27/12/2021
  3500                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility code
  3501                              <1> sysopen: ;<open file>
  3502                              <1> 	; 04/12/2021
  3503                              <1> 	; 07/08/2020 (Retro UNIX 386 v2)
  3504                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3505                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3506                              <1> 	;
  3507                              <1> 	; 'sysopen' opens a file in following manner:
  3508                              <1> 	;    1) The second argument in a sysopen says whether to
  3509                              <1> 	;	open the file to read (0) or write (>0).
  3510                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3511                              <1> 	;    3) The file is opened by 'iopen'.
  3512                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3513                              <1> 	;	and the user's open file list - u.fp.
  3514                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3515                              <1> 	;	b) An entry for the file is created in the fsp table.
  3516                              <1> 	;	c) The number of this entry is put on u.fp list.
  3517                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3518                              <1> 	;	   to by u.r0.
  3519                              <1> 	;
  3520                              <1> 	; Calling sequence:
  3521                              <1> 	;	sysopen; name; mode
  3522                              <1> 	; Arguments:
  3523                              <1> 	;	name - file name or path name
  3524                              <1> 	;	mode - 0 to open for reading
  3525                              <1> 	;	       1 to open for writing
  3526                              <1> 	; Inputs: (arguments)
  3527                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3528                              <1> 	;		  is put into r0's location on the stack.	
  3529                              <1> 	; ...............................................................
  3530                              <1> 	;				
  3531                              <1> 	; Retro UNIX 8086 v1 modification: 
  3532                              <1> 	;       'sysopen' system call has two arguments; so,
  3533                              <1> 	;	* 1st argument, name is pointed to by BX register
  3534                              <1> 	;	* 2nd argument, mode is in CX register
  3535                              <1> 	;
  3536                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3537                              <1> 	;	to the user with the file descriptor/number 
  3538                              <1> 	;	(index to u.fp list).
  3539                              <1> 	;
  3540                              <1> 	;call	arg2
  3541                              <1> 	; * name - 'u.namep' points to address of file/path name
  3542                              <1> 	;          in the user's program segment ('u.segmnt')
  3543                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3544                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3545                              <1> 	;          which is on top of stack.
  3546                              <1> 	;
  3547                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3548                              <1> 	;
  3549                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3550                              <1> 
  3551 00003E9B 891D[C4740000]      <1> 	mov	[u.namep], ebx
  3552 00003EA1 51                  <1> 	push	ecx ; * ; 04/12/2021 (cx -> ecx)
  3553 00003EA2 E8C80A0000          <1> 	call	namei
  3554                              <1> 		; jsr r0,namei / i-number of file in r1
  3555                              <1>      	;and	ax, ax
  3556                              <1> 	;jz	error ; File not found
  3557 00003EA7 722B                <1> 	jc	short fnotfound ; 14/05/2015
  3558                              <1> 	;jc	error ; 27/05/2013
  3559                              <1> 		; br  error2 / file not found
  3560                              <1>    	;pop	edx ; * ; mode ; 04/12/2021
  3561                              <1> 	;push	edx ; *
  3562                              <1> 	;;or	dx, dx
  3563                              <1> 	;or	dl, dl
  3564                              <1> 	;	; tst (sp) / is mode = 0 (2nd arg of call;
  3565                              <1> 	;	         ; / 0 means, open for read)
  3566                              <1> 	;;jz	short sysopen_0
  3567                              <1> 	;;	; beq 1f / yes, leave i-number positive
  3568                              <1> 	
  3569 00003EA9 8B1424              <1> 	mov	edx, [esp] ; *
  3570                              <1> 	; edx = open mode (0 or 1)
  3571                              <1> 
  3572                              <1> ;syscreat_0: ;op0: ; 27/12/2015
  3573                              <1> ;	neg	ax
  3574                              <1> ;        	; neg r1 / open for writing so make i-number negative
  3575                              <1> 
  3576                              <1> sysopen_0: ;1:
  3577 00003EAC E8C11E0000          <1> 	call	iopen
  3578                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3579 00003EB1 5A                  <1> 	pop	edx ; * ; mode ; 04/12/2021
  3580                              <1> 	;;and	dx, dx
  3581                              <1> 	;and	dl, dl
  3582                              <1>         ;	; tst (sp)+ / pop the stack and test the mode
  3583                              <1> 	;jz	short sysopen_2
  3584                              <1>         ;	; beq op1 / is open for read op1
  3585                              <1> ;sysopen_1: ;op0:
  3586                              <1> 	;neg	ax
  3587                              <1>         ;	; neg r1 
  3588                              <1> 	;	     ;/ make i-number positive if open for writing [???]
  3589                              <1> 
  3590                              <1> 	;; NOTE: iopen always make i-number positive.
  3591                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3592                              <1> sysopen_1: ; 04/12/2021
  3593                              <1> sysopen_2: ;op1:
  3594 00003EB2 31F6                <1>         xor     esi, esi
  3595                              <1>         	; clr r2 / clear registers
  3596 00003EB4 31DB                <1>         xor     ebx, ebx
  3597                              <1> 		; clr r3
  3598                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3599 00003EB6 389E[B2740000]      <1>         cmp     [esi+u.fp], bl ; 0
  3600                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3601 00003EBC 7625                <1> 	jna	short sysopen_4
  3602                              <1> 		; beq 1f / if byte in list is 0 branch
  3603 00003EBE 46                  <1>         inc     esi
  3604                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3605                              <1> 	; 02/01/2022
  3606                              <1> 	;cmp	si, OPENFILES ; 04/12/2021
  3607 00003EBF 6683FE0A            <1> 	cmp	si, 10
  3608                              <1> 		; cmp r2,$10. / reached end of list?
  3609 00003EC3 72F1                <1> 	jb	short sysopen_3
  3610                              <1> 		; blt 1b / no, go back
  3611                              <1> toomanyf:
  3612                              <1> 	; 14/05/2015
  3613 00003EC5 C705[1C750000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3613 00003ECD 0000                <1>
  3614 00003ECF E9FAFBFFFF          <1> 	jmp	error
  3615                              <1>         	; br error2 / yes, error (no files open)
  3616                              <1> fnotfound: 
  3617                              <1> 	; 14/05/2015
  3618 00003ED4 C705[1C750000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3618 00003EDC 0000                <1>
  3619 00003EDE E9EBFBFFFF          <1> 	jmp	error
  3620                              <1> 
  3621                              <1> sysopen_4: ; 1:
  3622 00003EE3 6683BB[44710000]00  <1>         cmp     word [ebx+fsp], 0
  3623                              <1> 		; tst fsp(r3) / scan fsp entries
  3624 00003EEB 760D                <1>         jna     short sysopen_5
  3625                              <1> 		; beq 1f / if 0 branch
  3626                              <1> 	;; 14/05/2015 - Retro UNIX 386 v1 modification !
  3627                              <1> 	;add	bx, 10 ; fsp structure size = 10 bytes/entry
  3628                              <1> 		; add $8.,r3 / add 8 to r3 
  3629                              <1> 			; / to bump it to next entry mfsp table
  3630                              <1> 	; 01/01/2022
  3631                              <1> 	; 07/08/2020 - Retro UNIX 386 v2
  3632 00003EED 6683C310            <1> 	add	bx, 16 ; fsp structure size = 16 bytes/entry ; runix v2
  3633                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  3634                              <1> 	;add	bx, fp.size
  3635                              <1> 
  3636                              <1> 	; 22/11/2021
  3637                              <1> 	;cmp	bx, NFILES*fp.size ; NFILES*16
  3638                              <1> 	; 02/01/2022
  3639 00003EF1 6681FB2003          <1> 	cmp	bx, nfiles*16
  3640                              <1> 	; 01/01/2022
  3641                              <1> 	;cmp	bx, NFILES*16 ; NFILES*fp.size
  3642                              <1> 	;;cmp	bx, nfiles*10
  3643                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3644 00003EF6 72EB                <1> 	jb	short sysopen_4
  3645                              <1>        		; blt 1b / no, back
  3646                              <1> 	;jmp	error
  3647                              <1>         ;	; br error2 / yes, error
  3648                              <1> 	; 04/12/2021
  3649                              <1> 	; 07/08/2020
  3650 00003EF8 EBCB                <1> 	jmp	short toomanyf
  3651                              <1> 
  3652                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3653 00003EFA 668983[44710000]    <1>         mov     [ebx+fsp], ax
  3654                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3655                              <1> 			; / into next available entry in fsp table,
  3656                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3657                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3658                              <1> 	;	; mov cdev,fsp+2(r3) / put # of device in next word
  3659                              <1> 
  3660                              <1> 	; 04/12/2021        
  3661 00003F01 A0[89740000]        <1> 	mov	al, [cdev]
  3662 00003F06 88D4                <1> 	mov	ah, dl ; open mode, 0 = read, 1 = write
  3663 00003F08 668983[48710000]    <1> 	mov	[ebx+fsp+4], ax ; device number & open mode
  3664                              <1> 
  3665                              <1> 	;xor	edi, edi
  3666                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3667                              <1> 	;	; clr fsp+4(r3)
  3668                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3669                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3670                              <1> 
  3671                              <1> 	; 04/12/2021 
  3672 00003F0F 31C0                <1> 	xor	eax, eax
  3673 00003F11 8983[4C710000]      <1>   	mov	[ebx+fsp+8], eax ; offset pointer = 0
  3674                              <1> 	;inc	word [ebx+fsp+6]
  3675 00003F17 FE83[4A710000]      <1> 	inc	byte [ebx+fsp+6] ; open count = open count + 1	
  3676                              <1> 
  3677                              <1>   	;mov	eax, ebx
  3678                              <1> 	;mov	bl, 10
  3679                              <1> 	;div	bl 
  3680                              <1> 	;	; asr r3
  3681                              <1> 	;	; asr r3 / divide by 8 
  3682                              <1> 	;	; asr r3 ; / to get number of the fsp entry-1
  3683                              <1> 	;inc	al
  3684                              <1>         ;	; inc r3 / add 1 to get fsp entry number
  3685                              <1>         ;mov	[esi+u.fp], al
  3686                              <1> 	;	; movb r3,u.fp(r2) / move entry number into 
  3687                              <1> 			; / next available slot in u.fp list
  3688                              <1> 	; 04/12/2021
  3689 00003F1D C1EB04              <1> 	shr	ebx, 4	; / 16
  3690                              <1> 	;shr	bx, 4	; bx = fsp entry number (index)	
  3691                              <1> 			; bx <= 49 for current runix 386 version
  3692 00003F20 FEC3                <1> 	inc 	bl	; bl = 1 to 50
  3693 00003F22 889E[B2740000]      <1> 	mov	[esi+u.fp], bl 	
  3694                              <1> 
  3695 00003F28 8935[A8740000]      <1>         mov     [u.r0], esi
  3696                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3697                              <1> 			     ; / into r0 loc on stack
  3698 00003F2E E9BBFBFFFF          <1>         jmp	sysret
  3699                              <1> 		; br sysret2
  3700                              <1> 
  3701                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  3702                              <1> ;
  3703                              <1> ;         15                    7                   0
  3704                              <1> ;  1     |-------------------------------------------|
  3705                              <1> ;        |   	     i-number of open file           |
  3706                              <1> ;        |-------------------------------------------| 
  3707                              <1> ;        |        high word of 32 bit i-number       |
  3708                              <1> ;        |-------------------------------------------|
  3709                              <1> ;        | open mode & status  |   device number     |
  3710                              <1> ;        |-------------------------------------------|			
  3711                              <1> ;        |    reserved byte    |     open count      |
  3712                              <1> ;        |-------------------------------------------| 
  3713                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3714                              <1> ;        |-------------------------------------------|
  3715                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3716                              <1> ;        |-------------------------------------------|
  3717                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3718                              <1> ;        |-------------------------------------------|
  3719                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3720                              <1> ;        |-------------------------------------------|
  3721                              <1> ;  2     |                                           |
  3722                              <1> ;        |-------------------------------------------| 
  3723                              <1> ;        |                                           |
  3724                              <1> ;        |-------------------------------------------|
  3725                              <1> ;        |                                           |
  3726                              <1> ;        |-------------------------------------------|
  3727                              <1> ;        |                                           |
  3728                              <1> ;        |-------------------------------------------| 
  3729                              <1> ;        |                                           | 
  3730                              <1> 
  3731                              <1> 	;
  3732                              <1> 	; 'fsp' table (10 bytes/entry)
  3733                              <1> 	; bit 15				   bit 0
  3734                              <1> 	; ---|-------------------------------------------
  3735                              <1> 	; r/w|		i-number of open file
  3736                              <1> 	; ---|-------------------------------------------
  3737                              <1> 	;		   device number
  3738                              <1> 	; -----------------------------------------------
  3739                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3740                              <1> 	; -----------------------------------------------
  3741                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3742                              <1> 	; ----------------------|------------------------
  3743                              <1> 	;  flag that says file 	| number of processes
  3744                              <1> 	;   has been deleted	| that have file open 
  3745                              <1> 	; ----------------------|------------------------
  3746                              <1> 	;
  3747                              <1> 
  3748                              <1> 	; 11/02/2022
  3749                              <1> 	; 01/01/2022
  3750                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3751                              <1> syscreat: ; < create file >
  3752                              <1> 	; 11/02/2022
  3753                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3754                              <1> 	; 04/04/2021
  3755                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3756                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3757                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3758                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3759                              <1> 	;
  3760                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3761                              <1> 	; u.namep points to name of the file and mode is put
  3762                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3763                              <1> 	; If the file aready exists, it's mode and owner remain 
  3764                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3765                              <1> 	; did not exist, an i-node is created with the new mode via
  3766                              <1> 	; 'maknod' whether or not the file already existed, it is
  3767                              <1> 	; open for writing. The fsp table is then searched for a free
  3768                              <1> 	; entry. When a free entry is found, proper data is placed
  3769                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3770                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3771                              <1> 	; is put in the user's r0. 			
  3772                              <1> 	;
  3773                              <1> 	; Calling sequence:
  3774                              <1> 	;	syscreate; name; mode
  3775                              <1> 	; Arguments:
  3776                              <1> 	;	name - name of the file to be created
  3777                              <1> 	;	mode - mode of the file to be created
  3778                              <1> 	; Inputs: (arguments)
  3779                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3780                              <1> 	;		   (the file descriptor of new file)
  3781                              <1> 	; ...............................................................
  3782                              <1> 	;				
  3783                              <1> 	; Retro UNIX 8086 v1 modification: 
  3784                              <1> 	;       'syscreate' system call has two arguments; so,
  3785                              <1> 	;	* 1st argument, name is pointed to by BX register
  3786                              <1> 	;	* 2nd argument, mode is in CX register
  3787                              <1> 	;
  3788                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3789                              <1> 	;	to the user with the file descriptor/number 
  3790                              <1> 	;	(index to u.fp list).
  3791                              <1> 	;
  3792                              <1> 	;call	arg2
  3793                              <1> 	; * name - 'u.namep' points to address of file/path name
  3794                              <1> 	;          in the user's program segment ('u.segmnt')
  3795                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3796                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3797                              <1> 	;          which is on top of stack.
  3798                              <1> 	;
  3799                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3800                              <1> 			    ; / on stack
  3801 00003F33 891D[C4740000]      <1> 	mov	[u.namep], ebx ; file name address
  3802                              <1> 	;push	cx ; mode
  3803                              <1> 	; 04/12/2021
  3804 00003F39 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3805 00003F3A E8300A0000          <1> 	call 	namei        	
  3806                              <1> 		; jsr r0,namei / get the i-number
  3807                              <1>         ;and	ax, ax
  3808                              <1> 	;jz	short syscreat_1	       	
  3809 00003F3F 7214                <1> 	jc	short syscreat_1
  3810                              <1> 		; br 2f / if file doesn't exist 2f
  3811                              <1> 	; 27/12/2015
  3812                              <1> 	;cmp	ax, 41 ; device inode ?
  3813                              <1>         ;jb	syscreat_0 ; yes
  3814                              <1> 	;
  3815                              <1> 	;neg 	ax
  3816                              <1>         ;	; neg r1 / if file already exists make i-number 
  3817                              <1> 		       ; / negative (open for writing)
  3818                              <1> 	; 11/02/2022
  3819                              <1> 	; Truncate existing file
  3820                              <1> ;syscreate_2:
  3821                              <1> 	;; 27/03/2021
  3822                              <1> 	;;xor	edx, edx ; 0
  3823                              <1> 	;;inc	dl ; DL = 1 ; create/truncate (open for write)
  3824                              <1> 	;mov	dl, 1
  3825                              <1> 	; 11/02/2022
  3826 00003F41 B202                <1> 	mov	dl, 2 ; create file (call from syscreat)
  3827 00003F43 E82A1E0000          <1> 	call	iopen
  3828                              <1>          	; jsr r0,iopen /
  3829                              <1> 	; 11/02/2022
  3830                              <1> 	; cpu will return here if inode in eax is regular file inode
  3831                              <1> 	; (if it is device or dir inode, cpu will jumpt to 'error')
  3832                              <1> 	; 
  3833                              <1> 	; truncate file to zero length
  3834                              <1> 	;call	itrunc
  3835                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3836                              <1> 	; 11/02/2022
  3837                              <1> 	; (iget and regular file check -in 'itrunc'- is not needed) 
  3838 00003F48 E8BD160000          <1> 	call	itrunc_1
  3839                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3840                              <1> 	; 04/12/2021
  3841 00003F4D 59                  <1> 	pop	ecx
  3842                              <1> syscreat_2:
  3843 00003F4E B201                <1> 	mov	dl, 1 ; open for writing
  3844 00003F50 E95DFFFFFF          <1>         jmp     sysopen_1
  3845                              <1>         	; br op0
  3846                              <1> syscreat_1: ; 2: / file doesn't exist
  3847                              <1> 	;pop	ax
  3848                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3849                              <1> 	; 27/03/2021
  3850 00003F55 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3851                              <1> 	;xor	ah, ah	
  3852                              <1>         ;	; bic $!377,r1 / clear upper byte
  3853                              <1> 	; 27/03/2021
  3854                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  3855                              <1> 	; clear bits 15,14,13,12,9 of mode (input from user)
  3856 00003F56 80E40D              <1> 	and	ah, 0Dh ; ISUID (800h) & ISGID (400h) & IREAD (100h)
  3857                              <1> 	; 11/02/2022
  3858 00003F59 80CC80              <1> 	or	ah, 80h	; IFREG (8000h) ; Regular file
  3859 00003F5C E8080D0000          <1> 	call 	maknod
  3860                              <1>         	; jsr r0,maknod / make an i-node for this file
  3861                              <1> 	;sub	eax, eax ; 04/12/2021
  3862 00003F61 66A1[E0740000]      <1> 	mov	ax, [u.dirbuf]
  3863                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3864                              <1> 			        ; / for this new file in r1
  3865                              <1> 	; 04/04/2021
  3866                              <1> 	;mov	dl, 1 ; open for writing
  3867                              <1>         ;
  3868                              <1> 	;jmp	sysopen_1
  3869                              <1>         ;	; br op0 / open the file
  3870                              <1> 	; 04/04/2021
  3871 00003F67 EBE5                <1> 	jmp	short syscreat_2
  3872                              <1> 
  3873                              <1> 	; 11/02/2022
  3874                              <1> ;	; 04/12/2021
  3875                              <1> ;dir_access_err:
  3876                              <1> ;	; 14/05/2015
  3877                              <1> ;	;mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3878                              <1> ;f_create_error:
  3879                              <1> ;	; 27/03/2021
  3880                              <1> ;	mov	dword [u.error], ERR_PERM_DENIED ; permission denied !	
  3881                              <1> ;	jmp	error
  3882                              <1> 
  3883                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3884                              <1> sysmkdir: ; < make directory >
  3885                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3886                              <1> 	; 02/04/2021
  3887                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3888                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3889                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3890                              <1> 	;
  3891                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3892                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3893                              <1> 	; The special entries '.' and '..' are not present.
  3894                              <1> 	; Errors are indicated if the directory already exists or		
  3895                              <1> 	; user is not the super user. 
  3896                              <1> 	;
  3897                              <1> 	; Calling sequence:
  3898                              <1> 	;	sysmkdir; name; mode
  3899                              <1> 	; Arguments:
  3900                              <1> 	;	name - points to the name of the directory
  3901                              <1> 	;	mode - mode of the directory
  3902                              <1> 	; Inputs: (arguments)
  3903                              <1> 	; Outputs: -
  3904                              <1> 	;    (sets 'directory' flag to 1; 
  3905                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3906                              <1> 	; ...............................................................
  3907                              <1> 	;				
  3908                              <1> 	; Retro UNIX 8086 v1 modification: 
  3909                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3910                              <1> 	;	* 1st argument, name is pointed to by BX register
  3911                              <1> 	;	* 2nd argument, mode is in CX register
  3912                              <1> 	;
  3913                              <1> 		
  3914                              <1> ; / make a directory
  3915                              <1> 
  3916                              <1> 	;call	arg2
  3917                              <1> 	; * name - 'u.namep' points to address of file/path name
  3918                              <1> 	;          in the user's program segment ('u.segmnt')
  3919                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3920                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3921                              <1> 	;          which is on top of stack.
  3922                              <1> 
  3923                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3924                              <1> 			    ; / on stack
  3925 00003F69 891D[C4740000]      <1> 	mov	[u.namep], ebx
  3926                              <1> 	;push	cx ; mode
  3927                              <1> 	; 27/03/2021
  3928 00003F6F 51                  <1> 	push	ecx ; cx = mode
  3929 00003F70 E8FA090000          <1> 	call	namei
  3930                              <1>         	; jsr r0,namei / get the i-number
  3931                              <1>         	;     br .+4 / if file not found branch around error
  3932                              <1>         ;xor 	ax, ax
  3933                              <1> 	;jnz	error
  3934 00003F75 7312                <1> 	jnc	short dir_exists ; 14/05/2015
  3935                              <1> 	;jnc	error	
  3936                              <1> 		; br error2 / directory already exists (error)
  3937                              <1> 
  3938                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  3939                              <1>         ;	;tstb u.uid / is user the super user
  3940                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3941                              <1> 	;;jna	error
  3942                              <1>         ;	;bne error2 / no, not allowed
  3943                              <1> 	;pop	ax
  3944                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3945                              <1> 	;and	ax, 0FFCFh ; 1111111111001111b
  3946                              <1>         ;	;bic $!317,r1 / all but su and ex
  3947                              <1> 	;;or	ax, 4000h ; 1011111111111111b
  3948                              <1> 	;or	ah, 40h ; Set bit 14 to 1
  3949                              <1>         ; 	;bis $40000,r1 / directory flag
  3950                              <1> 
  3951                              <1> 	; 02/04/2021
  3952                              <1> 	;cmp	word [u.uid], 0
  3953                              <1> 	;ja	error
  3954                              <1> 
  3955                              <1> 	; 02/04/2021
  3956                              <1> 	; ('mkdir' procedure will be called from 'maknod'
  3957                              <1> 	; and then 'mkdir' will check write access permission) 
  3958                              <1> 	; ((so, 'access_w' call is not needed here.))
  3959                              <1> 
  3960                              <1> 	;; 02/04/2021
  3961                              <1> 	;; ('make directory' user permission check)
  3962                              <1> 	;; ((current directory's write permission flags
  3963                              <1> 	;;  will be checked against user's 'uid' & gid'))
  3964                              <1> 	;mov	dx, 80h ; IWRITE
  3965                              <1> 	;call	access_w  ; (in 'access', 'u5.s')
  3966                              <1> 	;; (If cpu will return here, the user has write permission)
  3967                              <1> 		
  3968                              <1> 	; 27/03/2021
  3969 00003F77 58                  <1> 	pop	eax  ; ax = mode
  3970                              <1> 	; [ii] = current directory's inode number
  3971                              <1> 
  3972                              <1> 	; 27/03/2021
  3973                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  3974                              <1> 	; clear bits 13,12,11,10,9,6,3,0 of mode (input from user)
  3975                              <1> 	;and	ax, 0C1B6h ; bits 15,14,8,7,5,4,2,1
  3976 00003F78 6625B601            <1> 	and	ax, 01B6h
  3977 00003F7C 80CCC0              <1> 	or	ah, 0C0h ; IFREG (8000h) + IFDIR (4000h) 
  3978                              <1> 			 ; Directory
  3979 00003F7F E8E50C0000          <1> 	call	maknod
  3980                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3981 00003F84 E965FBFFFF          <1> 	jmp	sysret
  3982                              <1>         	;br sysret2 /
  3983                              <1> dir_exists:
  3984                              <1> 	; 27/03/2021
  3985                              <1> 	; (same error number for files and directories)
  3986                              <1> 	; Error Number: 14 (ERR_DIR_EXISTS)
  3987 00003F89 C705[1C750000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS
  3987 00003F91 0000                <1>
  3988                              <1> 				; 'file already exists !' error
  3989                              <1> 	; 04/12/2021
  3990 00003F93 E936FBFFFF          <1> 	jmp	error
  3991                              <1> ;dir_access_err:
  3992                              <1> ;	; 14/05/2015
  3993                              <1> ;	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3994                              <1> ;	jmp	error
  3995                              <1> 
  3996                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3997                              <1> sysclose: ;<close file>
  3998                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3999                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4000                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  4001                              <1> 	;
  4002                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  4003                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  4004                              <1> 	; is put in r1 and 'fclose' is called.
  4005                              <1> 	;
  4006                              <1> 	; Calling sequence:
  4007                              <1> 	;	sysclose
  4008                              <1> 	; Arguments:
  4009                              <1> 	;	-  
  4010                              <1> 	; Inputs: *u.r0 - file descriptor
  4011                              <1> 	; Outputs: -
  4012                              <1> 	; ...............................................................
  4013                              <1> 	;				
  4014                              <1> 	; Retro UNIX 8086 v1 modification:
  4015                              <1> 	;	 The user/application program puts file descriptor
  4016                              <1> 	;        in BX register as 'sysclose' system call argument.
  4017                              <1> 	; 	 (argument transfer method 1)
  4018                              <1> 
  4019                              <1> 	; / close the file
  4020                              <1> 	
  4021                              <1> 	;mov 	eax, ebx
  4022                              <1> 	; 04/12/2021
  4023                              <1> 	; ebx = file descriptor/number
  4024 00003F98 E856090000          <1> 	call 	fclose
  4025                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  4026                              <1> 		; jsr r0,fclose / close the file
  4027                              <1>                	; br error2 / unknown file descriptor
  4028                              <1> 		; br sysret2
  4029                              <1> 	;; 14/05/2015
  4030                              <1> 	;jnc	sysret
  4031                              <1> 	; 04/12/2021
  4032 00003F9D 7205                <1> 	jc	short sysclose_1
  4033 00003F9F E94AFBFFFF          <1> 	jmp	sysret
  4034                              <1> sysclose_1:
  4035 00003FA4 C705[1C750000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  4035 00003FAC 0000                <1>
  4036 00003FAE E91BFBFFFF          <1> 	jmp	error
  4037                              <1> 
  4038                              <1> 	; 19/12/2021
  4039                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4040                              <1> sysemt:
  4041                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4042                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4043                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  4044                              <1> 	;
  4045                              <1> 	; Retro UNIX 8086 v1 modification: 
  4046                              <1> 	;	'Enable Multi Tasking' system call instead 
  4047                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  4048                              <1> 	;
  4049                              <1> 	; Retro UNIX 8086 v1 feature only!
  4050                              <1> 	;	Using purpose: Kernel will start without time-out
  4051                              <1> 	;	(internal clock/timer) functionality.
  4052                              <1> 	;	Then etc/init will enable clock/timer for
  4053                              <1> 	;	multi tasking. (Then it will not be disabled again
  4054                              <1> 	;	except hardware reset/restart.)
  4055                              <1> 	;
  4056                              <1> 	
  4057                              <1> 	;cmp	byte [u.uid], 0 ; root ?
  4058                              <1> 	;;ja	error
  4059                              <1> 	;ja	badsys ; 14/05/2015
  4060                              <1> 	; 04/12/2021
  4061 00003FB3 66833D[FA740000]00  <1> 	cmp	word [u.uid], 0 ; root ?
  4062 00003FBB 7605                <1> 	jna	short emt_0 
  4063 00003FBD E9BEFBFFFF          <1> 	jmp	badsys
  4064                              <1> emt_0:
  4065                              <1> 	; 19/12/2021
  4066                              <1> 	;cli
  4067 00003FC2 21DB                <1> 	and	ebx, ebx
  4068 00003FC4 740F                <1> 	jz	short emt_2
  4069                              <1> 	; Enable multi tasking -time sharing-
  4070 00003FC6 B8[924F0000]        <1> 	mov	eax, clock
  4071                              <1> emt_1:
  4072 00003FCB A3[0F070000]        <1> 	mov	[x_timer], eax
  4073                              <1> 	;sti
  4074 00003FD0 E919FBFFFF          <1> 	jmp	sysret
  4075                              <1> emt_2:
  4076                              <1> 	; Disable multi tasking -time sharing-
  4077 00003FD5 B8[17070000]        <1> 	mov	eax, u_timer
  4078 00003FDA EBEF                <1> 	jmp	short emt_1
  4079                              <1> 
  4080                              <1> 	; Original UNIX v1 'sysemt' routine
  4081                              <1> ;sysemt:
  4082                              <1>         ;
  4083                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  4084                              <1> 			 ; / in loc 30
  4085                              <1>         ;cmp    30,$core / was the argument a lower address 
  4086                              <1> 			; / than core
  4087                              <1>         ;blo    1f / yes, rtssym
  4088                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  4089                              <1> 			; / and less than "ecore"
  4090                              <1>         ;blo    2f / yes, sysret2
  4091                              <1> ;1:
  4092                              <1>         ;mov    $rtssym,30
  4093                              <1> ;2:
  4094                              <1>         ;br     sysret2
  4095                              <1> 
  4096                              <1> sysilgins:
  4097                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4098                              <1> 	; 03/06/2013
  4099                              <1> 	; Retro UNIX 8086 v1 modification: 
  4100                              <1> 	;	not a valid system call ! (not in use)
  4101                              <1> 	;
  4102 00003FDC E99FFBFFFF          <1> 	jmp	badsys
  4103                              <1> 	;jmp	error
  4104                              <1> 	;;jmp 	sysret
  4105                              <1> 
  4106                              <1> 	; Original UNIX v1 'sysemt' routine
  4107                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  4108                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  4109                              <1> 			  ;/ put it in loc 8.,
  4110                              <1>         ;cmp    10,$core / making it the illegal instruction 
  4111                              <1> 		       ; / trap address
  4112                              <1>         ;blo    1f / is the address a user core address?  
  4113                              <1> 		; / yes, go to 2f
  4114                              <1>         ;cmp    10,$ecore
  4115                              <1>         ;blo    2f
  4116                              <1> ;1:
  4117                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  4118                              <1> 		    ; / instruction trap address for the system
  4119                              <1> ;2:
  4120                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  4121                              <1> 
  4122                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4123                              <1> sysmdate: ; < change the modification time of a file >
  4124                              <1> 	; 24/12/2021
  4125                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4126                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  4127                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4128                              <1> 	;
  4129                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  4130                              <1> 	; file into core. The user is checked if he is the owner 
  4131                              <1> 	; or super user. If he is neither an error occurs.
  4132                              <1> 	; 'setimod' is then called to set the i-node modification
  4133                              <1> 	; byte and the modification time, but the modification time
  4134                              <1> 	; is overwritten by whatever get put on the stack during
  4135                              <1> 	; a 'systime' system call. This calls are restricted to
  4136                              <1> 	; the super user.		
  4137                              <1> 	;
  4138                              <1> 	; Calling sequence:
  4139                              <1> 	;	sysmdate; name
  4140                              <1> 	; Arguments:
  4141                              <1> 	;	name - points to the name of file
  4142                              <1> 	; Inputs: (arguments)
  4143                              <1> 	; Outputs: -
  4144                              <1> 	; ...............................................................
  4145                              <1> 	;				
  4146                              <1> 	; Retro UNIX 8086 v1 modification: 
  4147                              <1> 	;	 The user/application program puts address 
  4148                              <1> 	;	 of the file name in BX register 
  4149                              <1> 	;	 as 'sysmdate' system call argument.
  4150                              <1> 	;
  4151                              <1> ; / change the modification time of a file
  4152                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  4153 00003FE1 891D[C4740000]      <1>         mov	[u.namep], ebx
  4154 00003FE7 E883090000          <1> 	call	namei
  4155                              <1> 		; jsr r0,namei / get its i-number
  4156                              <1> 	;;jc	error       
  4157                              <1> 	;	; br error2 / no, such file
  4158                              <1> 	;jc	fnotfound ; file not found !
  4159                              <1> 	; 24/12/2021
  4160 00003FEC 7305                <1> 	jnc	short mdate_0
  4161 00003FEE E9E1FEFFFF          <1> 	jmp	fnotfound
  4162                              <1> mdate_0: 
  4163 00003FF3 E80C140000          <1> 	call	iget
  4164                              <1> 		; jsr r0,iget / get i-node into core
  4165                              <1> 	;mov	al, [u.uid]
  4166                              <1> 	;cmp	al, [i.uid]
  4167                              <1>         ;	; cmpb u.uid,i.uid / is user same as owner
  4168                              <1> 	;je	short mdate_1
  4169                              <1>         ;	; beq 1f / yes
  4170                              <1> 	;and	al, al
  4171                              <1> 	;	; tstb u.uid / no, is user the super user
  4172                              <1> 	;;jnz	error
  4173                              <1> 	;	; bne error2 / no, error
  4174                              <1> 	;jz	short mdate_1
  4175                              <1> 	; 04/12/2021
  4176 00003FF8 66A1[FA740000]      <1> 	mov	ax, [u.uid]
  4177 00003FFE 663B05[48700000]    <1> 	cmp	ax, [i.uid]
  4178 00004005 7414                <1> 	je	short mdate_1	
  4179 00004007 6621C0              <1> 	and	ax, ax
  4180 0000400A 740F                <1> 	jz	short mdate_1
  4181                              <1> 
  4182 0000400C C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4182 00004014 0000                <1>
  4183                              <1> sysstty_err:	; 06/02/2022
  4184 00004016 E9B3FAFFFF          <1> 	jmp	error
  4185                              <1> mdate_1: ;1:
  4186 0000401B E883150000          <1> 	call	setimod
  4187                              <1>         	; jsr r0,setimod / fill in modification data,
  4188                              <1> 		               ; / time etc.
  4189 00004020 BE[D06F0000]        <1> 	mov	esi, p_time
  4190 00004025 BF[7C700000]        <1> 	mov	edi, i.mtim
  4191 0000402A A5                  <1> 	movsd
  4192                              <1> 		; mov 4(sp),i.mtim / move present time to
  4193                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4194 0000402B E9BEFAFFFF          <1>         jmp	sysret
  4195                              <1> 		; br sysret2
  4196                              <1> 
  4197                              <1> 	; 06/02/2022
  4198                              <1> sysstty_err_s:
  4199 00004030 880D[A8740000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4200 00004036 EBDE                <1> 	jmp	short sysstty_err
  4201                              <1> 
  4202                              <1> sysstty: ; < set tty status and mode >
  4203                              <1> 	; 06/02/2022 (Retro UNIX 286 v1.2)
  4204                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4205                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4206                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4207                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4208                              <1> 	;	    ((32 bit reg push/pop))
  4209                              <1> 	; 17/11/2015
  4210                              <1> 	; 12/11/2015
  4211                              <1> 	; 29/10/2015
  4212                              <1> 	; 17/10/2015
  4213                              <1> 	; 13/10/2015
  4214                              <1> 	; 29/06/2015
  4215                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4216                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4217                              <1> 	;
  4218                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4219                              <1> 	; whose file descriptor is in (u.r0).
  4220                              <1> 	;
  4221                              <1> 	; Calling sequence:
  4222                              <1> 	;	sysstty; arg
  4223                              <1> 	; Arguments:
  4224                              <1> 	;	arg - address of 3 consequitive words that contain
  4225                              <1> 	;	      the source of status data	
  4226                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4227                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4228                              <1> 	; ...............................................................
  4229                              <1> 	;	
  4230                              <1> 	; Retro UNIX 8086 v1 modification: 
  4231                              <1> 	;	'sysstty' system call will set the tty
  4232                              <1> 	;	(clear keyboard buffer and set cursor position)
  4233                              <1> 	;	 in following manner:
  4234                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4235                              <1> 	;
  4236                              <1> 	; Inputs:
  4237                              <1> 	;	BX = 0 --> means
  4238                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4239                              <1> 	;	      set cursor position for console tty, only 
  4240                              <1> 	;	      CH will be ignored (char. will not be written)
  4241                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4242                              <1> 	;	      set console tty for (current) process
  4243                              <1> 	;	      CL = tty number (0 to 9)
  4244                              <1> 	;	      (If CH = 0, character will not be written)
  4245                              <1> 	;          If CH > 0 (CL < FFh)	
  4246                              <1> 	;             CL = tty number (0 to 9)
  4247                              <1> 	;	      CH = character will be written
  4248                              <1> 	;	        at requested cursor position (in DX)
  4249                              <1> 	;	   DX = cursor position for tty number 0 to 7.
  4250                              <1>   	;		(only tty number 0 to 7) 
  4251                              <1> 	;          DL = communication parameters (for serial ports)
  4252                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4253                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4254                              <1> 	;			or set cursor position	
  4255                              <1> 	;	   DH = 0FFh -> DL is not valid
  4256                              <1> 	;		do not set serial port parameters 
  4257                              <1> 	;		or do not set cursor position
  4258                              <1> 	;
  4259                              <1> 	;	BX > 0 --> points to name of tty
  4260                              <1> 	;    	   CH > 0 -->
  4261                              <1> 	;		CH = character will be written in current 
  4262                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4263                              <1> 	;	     	or character will be sent to serial port
  4264                              <1> 	;	     	(for tty number 8 or 9)
  4265                              <1> 	;		CL = color of the character if tty number < 8.
  4266                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4267                              <1> 	;		set mode (tty 8 to 9) or 
  4268                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4269                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4270                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4271                              <1> 	;		(DL is not valid)
  4272                              <1> 	;	   DL = communication parameters 
  4273                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4274                              <1> 	;
  4275                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4276                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4277                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4278                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4279                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4280                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4281                              <1> 	;
  4282                              <1> 	; Outputs:
  4283                              <1> 	;	cf = 0 -> OK
  4284                              <1> 	;	     AL = tty number (0 to 9)
  4285                              <1> 	;	     AH = line status if tty number is 8 or 9
  4286                              <1> 	;	     AH = process number (of the caller)
  4287                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4288                              <1> 	;	     AH = FFh if the tty is locked 
  4289                              <1> 	;		  (owned by another process)
  4290                              <1> 	;	        = process number (of the caller) 
  4291                              <1> 	;		  (if < FFh and tty number < 8)
  4292                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4293                              <1> 	;	     AH = line status if tty number is 8 or 9
  4294                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4295                              <1> 	;	
  4296                              <1> 
  4297                              <1> 	; 27/06/2015 (32 bit modifications)
  4298                              <1> 	; 14/01/2014
  4299 00004038 31C0                <1> 	xor 	eax, eax
  4300 0000403A 6648                <1> 	dec	ax ; 17/10/2015
  4301 0000403C A3[A8740000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4302                              <1> 	;;;
  4303                              <1> 	; 01/02/2022
  4304 00004041 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4305 00004043 39C2                <1> 	cmp	edx, eax
  4306                              <1> 	;cmp	dx, ax ; 0FFFFh
  4307 00004045 7521                <1> 	jne	short sysstty_18
  4308                              <1> 	; clear video page
  4309                              <1> 	; (CH must be 0)
  4310 00004047 08ED                <1> 	or	ch, ch
  4311 00004049 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4312 0000404B 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4313 0000404E 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4314 00004050 20C9                <1> 	and	cl, cl
  4315 00004052 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4316 00004054 0FB635[F9740000]    <1> 	movzx	esi, byte [u.uno]
  4317 0000405B 8A8E[C3700000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4318 00004061 80F907              <1> 	cmp	cl, 7
  4319 00004064 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4320                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4321 00004066 FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4322                              <1> sysstty_18:
  4323 00004068 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4324                              <1> 	; cl = video page (tty) number
  4325                              <1> 	;;;
  4326 0000406A 21DB                <1> 	and	ebx, ebx
  4327                              <1> 	;jnz	sysstty_6
  4328                              <1> 	; 01/02/2022
  4329 0000406C 7405                <1> 	jz	short sysstty_19
  4330 0000406E E9C2000000          <1> 	jmp	sysstty_6
  4331                              <1> sysstty_19:
  4332                              <1> 	; set console tty
  4333                              <1> 	; 29/10/2015
  4334                              <1> 	; 17/01/2014 
  4335 00004073 80F909              <1> 	cmp	cl, 9
  4336 00004076 7613                <1> 	jna	short sysstty_0
  4337                              <1> 	; 17/11/2015
  4338 00004078 80F9FF              <1> 	cmp	cl, 0FFh
  4339 0000407B 7202                <1> 	jb	short sysstty_13
  4340 0000407D 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4341                              <1> sysstty_13:
  4342 0000407F 8A1D[F9740000]      <1> 	mov	bl, [u.uno] ; process number
  4343 00004085 8A8B[C3700000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4344                              <1> sysstty_0:
  4345                              <1> 	; 29/06/2015
  4346 0000408B 52                  <1> 	push	edx ; 24/12/2021
  4347 0000408C 51                  <1> 	push	ecx
  4348 0000408D 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4349 0000408F 88C8                <1> 	mov	al, cl
  4350 00004091 A2[A8740000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4351 00004096 E8AC1D0000          <1> 	call	ottyp
  4352 0000409B 59                  <1> 	pop	ecx
  4353 0000409C 5A                  <1> 	pop	edx
  4354                              <1> 	;
  4355 0000409D 7220                <1> 	jc	short sysstty_pd_err
  4356                              <1> 	;
  4357 0000409F 80F908              <1> 	cmp	cl, 8
  4358 000040A2 720C                <1> 	jb	short sysstty_2
  4359                              <1> 	;
  4360 000040A4 80FEFF              <1> 	cmp	dh, 0FFh
  4361 000040A7 7407                <1> 	je	short sysstty_2
  4362                              <1> 
  4363                              <1> ; 01/02/2022
  4364                              <1> ;	; 29/10/2015
  4365                              <1> ;	mov	ah, dl ; communication parameters
  4366                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4367                              <1> ;		;			 THRE int + RDA int 
  4368                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4369                              <1> ;		;			 THRE int + RDA int 
  4370                              <1> ;	sub	al, al ; 0
  4371                              <1> ;	; 12/07/2014
  4372                              <1> ;	cmp	cl, 9
  4373                              <1> ;	jb	short sysstty_1
  4374                              <1> ;	inc	al
  4375                              <1> ;sysstty_1:
  4376                              <1> ;	; 01/02/2022
  4377                              <1> ;	push	ecx
  4378                              <1> ;	; 29/06/2015	
  4379                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4380                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4381                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4382                              <1> ;	; 01/02/2022
  4383                              <1> ;	pop	ecx	
  4384                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4385                              <1> 
  4386                              <1> 	; 01/02/2022
  4387 000040A9 E830010000          <1> 	call	sysstty_scp
  4388 000040AE 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4389                              <1> 
  4390                              <1> sysstty_2:
  4391                              <1> 	; 17/01/2014
  4392 000040B0 20ED                <1> 	and	ch, ch 	; set cursor position 
  4393                              <1> 			; or comm. parameters ONLY
  4394 000040B2 7527                <1> 	jnz	short sysstty_3
  4395                              <1> 	; 01/02/2022
  4396 000040B4 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4397 000040B8 7214                <1> 	jb	short sysstty_20
  4398                              <1> 	; clear screen (video page)
  4399 000040BA E93B010000          <1> 	jmp	sysstty_14
  4400                              <1> 
  4401                              <1> sysstty_pd_err: ; 29/06/2015
  4402                              <1> 	; 'permission denied !' error
  4403 000040BF C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4403 000040C7 0000                <1>
  4404 000040C9 E900FAFFFF          <1> 	jmp	error
  4405                              <1> 
  4406                              <1> sysstty_20:
  4407 000040CE 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4408 000040D5 888B[C3700000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4409                              <1> sysstty_3:
  4410                              <1> 	; 16/01/2014
  4411 000040DB 88E8                <1> 	mov	al, ch ; character  ; 0 to FFh
  4412                              <1> 	; 17/11/2015
  4413 000040DD B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4414 000040DF 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4415                              <1>         ;jna	sysstty_9
  4416                              <1> 	; 24/12/2021
  4417 000040E1 7705                <1> 	ja	short sysstty_12
  4418 000040E3 E9C7000000          <1> 	jmp	sysstty_9
  4419                              <1> 
  4420                              <1> sysstty_12:
  4421                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4422                              <1> 	; (Set specified serial port as console tty port)
  4423                              <1> 	; CH = character to be written
  4424                              <1> 	; 15/04/2014
  4425                              <1> 	; CH = 0 --> initialization only
  4426                              <1> 	; AL = character
  4427                              <1> 	; 26/06/2014
  4428 000040E8 880D[DD740000]      <1> 	mov	[u.ttyn], cl
  4429                              <1> 	; 12/07/2014
  4430 000040EE 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4431                              <1> 	; 02/02/2022
  4432 000040F0 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4433 000040F2 740B                <1> 	jz	short sysstty_4 ; al = ch = 0
  4434 000040F4 FEC8                <1> 	dec	al  ; 1 -> 0	
  4435                              <1> 	;and	al, al
  4436 000040F6 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4437                              <1>  	; 04/07/2014
  4438 000040F8 E891230000          <1> 	call 	sndc
  4439                              <1> 	; 12/07/2014
  4440 000040FD EB0C                <1> 	jmp	short sysstty_5
  4441                              <1> 
  4442                              <1> sysstty_4:
  4443                              <1> 	; 12/07/2014
  4444                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4445 000040FF 88E0                <1> 	mov	al, ah ; 29/06/2015
  4446 00004101 2C08                <1> 	sub	al, 8
  4447                              <1> 	; 27/06/2015
  4448 00004103 E862F4FFFF          <1> 	call	sp_status ; get serial port status
  4449                              <1> 	; AL = Line status, AH = Modem status
  4450                              <1> 	; 12/11/2015
  4451 00004108 3C80                <1> 	cmp	al, 80h
  4452 0000410A F5                  <1> 	cmc
  4453                              <1> sysstty_5:
  4454 0000410B 66A3[A9740000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4455                              <1> 		; EAX bits 16-23 = modem status	
  4456 00004111 9C                  <1> 	pushf
  4457 00004112 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4458 00004114 A0[DD740000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4459 00004119 E8501E0000          <1> 	call	cttyp
  4460 0000411E 9D                  <1> 	popf
  4461                              <1> 	;jnc	sysret ; time out error 
  4462                              <1> 	; 01/02/2022
  4463 0000411F 7205                <1> 	jc	short sysstty_tmout_err
  4464 00004121 E9C8F9FFFF          <1> 	jmp	sysret
  4465                              <1> 
  4466                              <1> 	; time out error 
  4467                              <1> sysstty_tmout_err:
  4468 00004126 C705[1C750000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4468 0000412E 0000                <1>
  4469 00004130 E999F9FFFF          <1> 	jmp	error
  4470                              <1> 
  4471                              <1> sysstty_6:
  4472 00004135 52                  <1> 	push	edx ; 24/12/2021
  4473 00004136 51                  <1> 	push	ecx
  4474 00004137 891D[C4740000]      <1> 	mov	[u.namep], ebx
  4475 0000413D E82D080000          <1> 	call	namei
  4476 00004142 59                  <1> 	pop	ecx
  4477 00004143 5A                  <1> 	pop	edx
  4478 00004144 7258                <1> 	jc	short sysstty_inv_dn
  4479                              <1> 	;
  4480 00004146 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4481 0000414A 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4482                              <1> 	;
  4483 0000414C 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4484                              <1> 		       ; /dev/COM1, /dev/COM2
  4485 0000414E 7204                <1> 	jb	short sysstty_7
  4486 00004150 2C0A                <1> 	sub	al, 10
  4487 00004152 EB11                <1> 	jmp	short sysstty_8
  4488                              <1>  
  4489                              <1> sysstty_7:
  4490 00004154 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4491 00004156 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4492 00004158 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4493 0000415F 8A83[C3700000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4494                              <1> sysstty_8:	
  4495 00004165 A2[A8740000]        <1> 	mov	[u.r0], al
  4496 0000416A 52                  <1> 	push	edx ; 24/12/2021
  4497 0000416B 50                  <1> 	push	eax
  4498 0000416C 51                  <1> 	push	ecx	
  4499 0000416D E8D51C0000          <1> 	call	ottyp
  4500 00004172 59                  <1> 	pop	ecx
  4501 00004173 58                  <1> 	pop	eax
  4502 00004174 5A                  <1> 	pop	edx
  4503                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4504                              <1> 	; 06/02/2022
  4505 00004175 7305                <1> 	jnc	short sysstty_21
  4506                              <1> 	; 'permission denied !'
  4507 00004177 E943FFFFFF          <1> 	jmp	sysstty_pd_err
  4508                              <1> sysstty_21:
  4509                              <1> 	; 29/10/2015
  4510 0000417C 86E9                <1> 	xchg 	ch, cl
  4511                              <1> 		; cl = character, ch = color code
  4512 0000417E 86C1                <1> 	xchg	al, cl
  4513                              <1> 		; al = character, cl = tty number
  4514 00004180 80F907              <1> 	cmp	cl, 7
  4515                              <1> 	;ja	sysstty_12
  4516                              <1> 	; 06/02/2022
  4517 00004183 7628                <1> 	jna	short sysstty_16
  4518                              <1> ;;
  4519 00004185 80FEFF              <1> 	cmp	dh, 0FFh
  4520 00004188 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4521                              <1> 
  4522                              <1> ; 01/02/2022
  4523                              <1> ;	; 29/10/2015
  4524                              <1> ;	mov	ah, dl ; communication parameters
  4525                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4526                              <1> ;		;			 THRE int + RDA int 
  4527                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4528                              <1> ;		;			 THRE int + RDA int 
  4529                              <1> ;	sub	al, al ; 0
  4530                              <1> ;	; 12/07/2014
  4531                              <1> ;	cmp	cl, 9
  4532                              <1> ;	jb	short sysstty_1
  4533                              <1> ;	inc	al
  4534                              <1> ;sysstty_1:
  4535                              <1> ;	; 01/02/2022
  4536                              <1> ;	push	ecx
  4537                              <1> ;	; 29/06/2015	
  4538                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4539                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4540                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4541                              <1> ;	; 01/02/2022
  4542                              <1> ;	pop	ecx	
  4543                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4544                              <1> 
  4545                              <1> 	; 02/02/2022
  4546 0000418A 88C5                <1> 	mov	ch, al ; save char
  4547                              <1> 	; 01/02/2022
  4548 0000418C E84D000000          <1> 	call	sysstty_scp
  4549 00004191 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4550                              <1> 	; 02/02/2022
  4551 00004193 88E8                <1> 	mov	al, ch ; restore char
  4552                              <1> sysstty_22:
  4553                              <1> 	; 01/02/2022
  4554 00004195 08ED                <1> 	or	ch, ch
  4555 00004197 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4556                              <1> 	; send char to (serial port) terminal
  4557                              <1> 	; al = character
  4558                              <1> 	; cl = tty number (8 or 9)
  4559 00004199 E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4560                              <1> 
  4561                              <1> sysstty_inv_dn: 
  4562                              <1> 	; 27/06/2015
  4563                              <1> 	; Invalid device name (not a tty) ! error
  4564                              <1> 	; (Device is not a tty or device name not found)
  4565 0000419E C705[1C750000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4565 000041A6 0000                <1>
  4566 000041A8 E921F9FFFF          <1> 	jmp	error
  4567                              <1> 
  4568                              <1> sysstty_16:
  4569                              <1> 	; 16/01/2014
  4570 000041AD 30FF                <1> 	xor	bh, bh
  4571                              <1> 	;
  4572                              <1> sysstty_9: 	; tty 0 to tty 7
  4573                              <1> 	; al = character
  4574                              <1> 	; ch = color/attribute ; 01/02/2022
  4575 000041AF 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4576 000041B2 740B                <1> 	je	short sysstty_10
  4577                              <1> 	; 24/12/2021
  4578 000041B4 51                  <1> 	push	ecx
  4579 000041B5 50                  <1> 	push	eax	
  4580                              <1> 	;movzx	ebx, cl
  4581 000041B6 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4582 000041B8 E807D3FFFF          <1> 	call	set_cpos
  4583 000041BD 58                  <1> 	pop	eax
  4584 000041BE 59                  <1> 	pop	ecx
  4585                              <1> sysstty_10: 
  4586                              <1> 	; 29/10/2015
  4587 000041BF 08C0                <1> 	or	al, al ; character
  4588 000041C1 740D                <1> 	jz      short sysstty_11 ; al = 0
  4589                              <1> 	; 17/11/2015
  4590 000041C3 3CFF                <1> 	cmp	al, 0FFh
  4591 000041C5 7309                <1> 	jnb	short sysstty_11
  4592                              <1> 		; ch > 0 and ch < FFh
  4593                              <1> 	; write a character at current cursor position
  4594 000041C7 88EC                <1> 	mov	ah, ch ; color/attribute
  4595                              <1> 	; 12/07/2014
  4596 000041C9 51                  <1> 	push	ecx ; 24/12/2021
  4597 000041CA E8DDD3FFFF          <1> 	call	write_c_current
  4598 000041CF 59                  <1> 	pop	ecx
  4599                              <1> sysstty_11:
  4600                              <1> 	; 14/01/2014
  4601 000041D0 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4602                              <1> 	; 18/01/2014
  4603                              <1> 	;movzx	eax, cl ; 27/06/2015
  4604 000041D2 88C8                <1> 	mov	al, cl
  4605 000041D4 E8951D0000          <1> 	call	cttyp
  4606 000041D9 E910F9FFFF          <1> 	jmp	sysret
  4607                              <1> 
  4608                              <1> 	; 06/02/2022 (Retro UNIX 386 v1.2)
  4609                              <1> sysstty_scp:
  4610                              <1> 	; 02/02/2022
  4611                              <1> 	; set communication parameters (for COM1 or COM2)
  4612                              <1> 	; 01/02/2022
  4613                              <1> 	;
  4614                              <1> 	; 29/10/2015
  4615 000041DE 88D4                <1> 	mov	ah, dl ; communication parameters
  4616                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4617                              <1> 		;			 THRE int + RDA int 
  4618                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4619                              <1> 		;			 THRE int + RDA int 
  4620 000041E0 28C0                <1> 	sub	al, al ; 0
  4621                              <1> 	; 12/07/2014
  4622 000041E2 80F909              <1> 	cmp	cl, 9
  4623 000041E5 7202                <1> 	jb	short sysstty_1
  4624 000041E7 FEC0                <1> 	inc	al
  4625                              <1> sysstty_1:
  4626                              <1> 	; 02/02/2022
  4627 000041E9 52                  <1> 	push	edx
  4628                              <1> 	; 01/02/2022
  4629 000041EA 51                  <1> 	push	ecx
  4630                              <1> 	; 29/06/2015	
  4631 000041EB E882F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4632 000041F0 66890D[A9740000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4633                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4634                              <1> 	; 01/02/2022
  4635 000041F7 59                  <1> 	pop	ecx	
  4636 000041F8 5A                  <1> 	pop	edx ; 02/02/2022
  4637                              <1> 	; 01/02/2022
  4638                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4639 000041F9 C3                  <1> 	retn
  4640                              <1> 
  4641                              <1> 	; 06/02/2022 (Retro UNIX 386 v1.2)
  4642                              <1> sysstty_14:
  4643                              <1> 	; 02/02/2022
  4644                              <1> 	; ch = 0
  4645                              <1> 	; cl = video page
  4646                              <1> 	;
  4647                              <1> 	; dx = 0FFFFh
  4648                              <1> 	; clear screen (video page)
  4649                              <1> 	;
  4650                              <1> 
  4651                              <1> 	; 02/02/2022
  4652                              <1> 	; clear screen
  4653                              <1> 	;
  4654                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4655                              <1> wttyc:
  4656                              <1> 	;xor	dx, dx ; column 0, row 0
  4657 000041FA 6642                <1> 	inc	dx ; 0
  4658                              <1> 	;
  4659                              <1> ;	movzx	ebx, cl
  4660 000041FC 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4661                              <1> 
  4662                              <1> ;	shl 	bl, 1 
  4663                              <1> ;	mov 	al, [ebx+ttyl]
  4664                              <1> ;		; AL = lock value (0 or process number)
  4665                              <1> ;	or	al, al
  4666                              <1> ;	jz	short @f
  4667                              <1> ;	cmp	al, [u.uno] ; process number
  4668                              <1> ;	jne	short sysstty_15
  4669                              <1> ;		; only the owner can clear its video page
  4670                              <1> ;	xor	al, al ; 0
  4671                              <1> ;@@:
  4672                              <1> ;	;mov	bl, cl
  4673                              <1> ;	shr	bl, 1 
  4674                              <1> 
  4675 000041FE 30C0                <1> 	xor	al, al	; 0
  4676 00004200 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4677                              <1> 
  4678                              <1> 	; scroll_up input:
  4679                              <1> 	;
  4680                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4681                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4682                              <1> 	; ah = attribute to be used on blanked line
  4683                              <1> 	; bl = video page number (0 to 7)
  4684                              <1> 
  4685 00004202 E843D3FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4686                              <1> 
  4687                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4688                              <1> 
  4689                              <1> 	; bl = video page number (0 to 7)
  4690                              <1> 	;xor	dx, dx ; column 0, row 0
  4691                              <1> 	; 02/02/2022
  4692 00004207 31D2                <1> 	xor	edx, edx
  4693 00004209 E8B6D2FFFF          <1> 	call	set_cpos
  4694                              <1> 	;
  4695 0000420E 88D8                <1> 	mov	al, bl
  4696 00004210 8A25[F9740000]      <1> 	mov	ah, [u.uno]
  4697 00004216 66A3[A8740000]      <1> 	mov	[u.r0], ax
  4698 0000421C EBB2                <1> 	jmp	short sysstty_11
  4699                              <1> 
  4700                              <1> ;sysstty_15:
  4701                              <1> ;	; 30/01/2022
  4702                              <1> ;	; permission (denied) error
  4703                              <1> ;	;xor	dl, dl ; sysstty call sign
  4704                              <1> ;	mov	al, cl
  4705                              <1> ;	sub	ah, ah ; 0
  4706                              <1> ;	call	cttyp
  4707                              <1> ;	jmp	error
  4708                              <1> 
  4709                              <1> ; Original UNIX v1 'sysstty' routine:
  4710                              <1> ; gtty:
  4711                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4712                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4713                              <1> 	; 		/ r2 has source
  4714                              <1>         ;mov    r2,-(sp)
  4715                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4716                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4717                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4718                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4719                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4720                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4721                              <1>         ;       br .+4 / list empty, skip branch
  4722                              <1>         ;br     1b / get another character until list is empty
  4723                              <1>         ;mov    0b,r1 / move cc offset to r1
  4724                              <1>         ;inc    r1 / bump it for output clist
  4725                              <1>         ;tstb   cc(r1) / is it 0
  4726                              <1>         ;beq    1f / yes, no characters to output
  4727                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4728                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4729                              <1>         ;br     1b / try to calm it down again
  4730                              <1> ;1:
  4731                              <1>         ;mov    (sp)+,r1
  4732                              <1>         ;mov    (sp)+,r2 / restore registers
  4733                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4734                              <1>         ;beq    1f / if 0, 1f
  4735                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4736                              <1>         ;                   / control status register
  4737                              <1> ;1:
  4738                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4739                              <1>         ;beq    1f / if 0 1f
  4740                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4741                              <1> 	;		    / control status reg
  4742                              <1> ;1:
  4743                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4744                              <1>         ;jmp     sysret2 / return to user
  4745                              <1> 
  4746                              <1> sysgtty: ; < get tty status >
  4747                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4748                              <1> 	;	    ((32 bit reg push/pop))
  4749                              <1> 	; 23/11/2015
  4750                              <1> 	; 29/10/2015
  4751                              <1> 	; 17/10/2015
  4752                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4753                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4754                              <1> 	;
  4755                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4756                              <1> 	; It stores in the three words addressed by it's argument
  4757                              <1> 	; the status of the typewriter whose file descriptor
  4758                              <1> 	; in (u.r0).
  4759                              <1> 	;
  4760                              <1> 	; Calling sequence:
  4761                              <1> 	;	sysgtty; arg
  4762                              <1> 	; Arguments:
  4763                              <1> 	;	arg - address of 3 words destination of the status
  4764                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4765                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4766                              <1> 	; ...............................................................
  4767                              <1> 	;	
  4768                              <1> 	; Retro UNIX 8086 v1 modification: 
  4769                              <1> 	;	'sysgtty' system call will return status of tty
  4770                              <1> 	;	(keyboard, serial port and video page status)
  4771                              <1> 	;	 in following manner:
  4772                              <1> 	;
  4773                              <1> 	; Inputs:
  4774                              <1> 	;	BX = 0 --> means 
  4775                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4776                              <1> 	;	                 for (current) process
  4777                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4778                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4779                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4780                              <1> 	;	     CH > 0 -->	tty number + 1
  4781                              <1> 	;
  4782                              <1> 	;	BX > 0 --> points to name of tty
  4783                              <1> 	;	     CL = 0 --> return keyboard status
  4784                              <1> 	;	     CL = 1 --> return video page status
  4785                              <1> 	;	     CH = undefined		 
  4786                              <1> 	;
  4787                              <1> 	; Outputs:
  4788                              <1> 	;	cf = 0 ->
  4789                              <1> 	;
  4790                              <1> 	;	     AL = tty number from 0 to 9
  4791                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4792                              <1> 	;	     AH = 0 if the tty is free/unused
  4793                              <1> 	;	     AH = the process number of the caller 
  4794                              <1>  	;	     AH = FFh if the tty is locked by another process
  4795                              <1> 	;
  4796                              <1> 	;	  (if calling is for serial port status)
  4797                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4798                              <1> 	;		  (BH = modem status, BL = Line status)
  4799                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4800                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4801                              <1> 	;
  4802                              <1> 	;	  (if calling is for keyboard status)
  4803                              <1> 	;	     BX = current character in tty/keyboard buffer
  4804                              <1> 	;		  (BH = scan code, BL = ascii code)
  4805                              <1> 	;		  (BX=0 if there is not a waiting character)
  4806                              <1> 	;	     CX  is undefined
  4807                              <1> 	;
  4808                              <1> 	;	  (if calling is for video page status)	
  4809                              <1> 	;	     BX = cursor position on the video page
  4810                              <1> 	;		  if tty number < 8
  4811                              <1> 	;		  (BH = row, BL = column)
  4812                              <1> 	;	     CX = current character (in cursor position)
  4813                              <1> 	;		  on the video page of the tty 
  4814                              <1> 	;		  if tty number < 8
  4815                              <1> 	;		  (CH = color, CL = character)
  4816                              <1> 	;	
  4817                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4818                              <1> 	;
  4819                              <1> 	;	     AH = FFh if the caller is not owner of
  4820                              <1> 	;		  specified tty or console tty
  4821                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4822                              <1> 	;	     BX, CX are undefined if cf = 1
  4823                              <1> 	;
  4824                              <1> 	;	  (If tty number is 8 or 9)
  4825                              <1> 	;	     AL = tty number 
  4826                              <1> 	;	     AH = the process number of the caller 
  4827                              <1> 	;	     BX = serial port status
  4828                              <1> 	;  		 (BH = modem status, BL = Line status)
  4829                              <1> 	;	     CX = 0
  4830                              <1> 	;
  4831                              <1> 		
  4832                              <1> gtty:   ; get (requested) tty number
  4833                              <1> 	; 17/10/2015
  4834                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4835                              <1> 	; 30/05/2013 - 12/07/2014
  4836                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4837                              <1> 	;
  4838                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4839                              <1> 	;
  4840                              <1> 	; 28/06/2015 (32 bit modifications)
  4841                              <1> 	; 16/01/2014
  4842 0000421E 31C0                <1> 	xor 	eax, eax
  4843 00004220 6648                <1> 	dec	ax ; 17/10/2015
  4844 00004222 A3[A8740000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4845 00004227 80F901              <1> 	cmp	cl, 1
  4846 0000422A 760F                <1> 	jna	short sysgtty_0
  4847                              <1> sysgtty_invp:
  4848                              <1> 	; 28/06/2015
  4849 0000422C C705[1C750000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4849 00004234 0000                <1>
  4850 00004236 E993F8FFFF          <1> 	jmp	error
  4851                              <1> sysgtty_0:	
  4852 0000423B 21DB                <1> 	and	ebx, ebx
  4853 0000423D 742E                <1> 	jz	short sysgtty_1
  4854                              <1> 	;
  4855 0000423F 891D[C4740000]      <1> 	mov	[u.namep], ebx
  4856                              <1> 	;push	cx ; 23/11/2015
  4857 00004245 51                  <1> 	push	ecx ; 24/12/2021
  4858 00004246 E824070000          <1> 	call	namei
  4859 0000424B 59                  <1> 	pop	ecx
  4860                              <1> 	;pop	cx ; 23/11/2015
  4861 0000424C 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4862                              <1> 	;
  4863 0000424E 6683F801            <1> 	cmp	ax, 1
  4864 00004252 7622                <1> 	jna	short sysgtty_2
  4865 00004254 6683E80A            <1> 	sub	ax, 10
  4866 00004258 6683F809            <1> 	cmp	ax, 9
  4867                              <1> 	;ja	short sysgtty_inv_dn
  4868                              <1> 	;mov	ch, al
  4869                              <1> 	;jmp	short sysgtty_4
  4870                              <1> 	; 23/11/2015
  4871 0000425C 7629                <1> 	jna	short sysgtty_4
  4872                              <1> sysgtty_inv_dn: 
  4873                              <1> 	; 28/06/2015
  4874                              <1> 	; Invalid device name (not a tty) ! error
  4875                              <1> 	; (Device is not a tty or device name not found)
  4876 0000425E C705[1C750000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4876 00004266 0000                <1>
  4877 00004268 E961F8FFFF          <1> 	jmp	error 
  4878                              <1> sysgtty_1:
  4879                              <1> 	; 16/01/2014
  4880 0000426D 80FD0A              <1> 	cmp	ch, 10
  4881 00004270 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4882 00004272 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4883 00004274 790F                <1> 	jns	short sysgtty_3 ; not negative
  4884                              <1> 	;
  4885                              <1> sysgtty_2:
  4886                              <1> 	; get tty number of console tty
  4887 00004276 8A25[F9740000]      <1> 	mov	ah, [u.uno]
  4888                              <1>  	; 28/06/2015
  4889 0000427C 0FB6DC              <1> 	movzx 	ebx, ah
  4890 0000427F 8AAB[C3700000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4891                              <1> sysgtty_3:
  4892 00004285 88E8                <1> 	mov	al, ch
  4893                              <1> sysgtty_4:
  4894 00004287 A2[A8740000]        <1> 	mov	[u.r0], al
  4895                              <1>  	; 28/06/2015
  4896                              <1> 	;cmp	al, 9
  4897                              <1> 	;ja	short sysgtty_invp
  4898 0000428C 8B2D[A4740000]      <1> 	mov	ebp, [u.usp]
  4899                              <1> 	; 23/11/2015
  4900 00004292 20C9                <1> 	and	cl, cl
  4901 00004294 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4902 00004296 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4903 00004298 722E                <1> 	jb	short sysgtty_6 ; video page status
  4904                              <1> 	; serial port status
  4905                              <1> 	; 12/07/2014
  4906                              <1> 	;mov	dx, 0
  4907                              <1> 	;je	short sysgtty_5
  4908                              <1> 	;inc	dl
  4909                              <1> ;sysgtty_5:
  4910                              <1> 	; 28/06/2015
  4911 0000429A 2C08                <1> 	sub	al, 8
  4912 0000429C E8C9F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4913                              <1> 	; AL = Line status, AH = Modem status
  4914 000042A1 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4915 000042A5 8A25[F9740000]      <1> 	mov	ah, [u.uno]
  4916 000042AB 8825[A9740000]      <1>         mov     [u.r0+1], ah
  4917                              <1> 	; 24/12/2021
  4918 000042B1 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4919                              <1> 				; (in ECX)
  4920 000042B7 A880                <1> 	test	al, 80h
  4921 000042B9 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4922 000042BB A801                <1> 	test	al, 1
  4923                              <1> 	;jz	sysret
  4924 000042BD 7404                <1> 	jz	short sysgtty_10
  4925 000042BF 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4926                              <1> sysgtty_10:
  4927 000042C3 E926F8FFFF          <1> 	jmp	sysret
  4928                              <1> sysgtty_6:
  4929 000042C8 A2[DD740000]        <1> 	mov	[u.ttyn], al ; tty number
  4930                              <1> 	;movzx	ebx, al
  4931 000042CD 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4932 000042CF D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4933                              <1> 	; 22/04/2014 - 29/06/2015
  4934 000042D1 81C3[D46F0000]      <1>         add     ebx, ttyl
  4935 000042D7 8A23                <1>  	mov	ah, [ebx]
  4936 000042D9 3A25[F9740000]      <1> 	cmp	ah, [u.uno]
  4937 000042DF 7404                <1> 	je	short sysgtty_7
  4938 000042E1 20E4                <1> 	and	ah, ah
  4939                              <1> 	;jz	short sysgtty_7
  4940 000042E3 7506                <1> 	jnz	short sysgtty_8
  4941                              <1> 	;mov	ah, 0FFh
  4942                              <1> sysgtty_7:
  4943 000042E5 8825[A9740000]      <1>         mov     [u.r0+1], ah
  4944                              <1> sysgtty_8:
  4945 000042EB 08C9                <1> 	or	cl, cl
  4946 000042ED 7510                <1> 	jnz	short sysgtty_9
  4947 000042EF B001                <1> 	mov	al, 1  ; test a key is available
  4948 000042F1 E81B210000          <1> 	call	getc
  4949 000042F6 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4950 000042FA E9EFF7FFFF          <1> 	jmp	sysret
  4951                              <1> sysgtty_9:
  4952 000042FF 8A1D[DD740000]      <1> 	mov	bl, [u.ttyn]
  4953                              <1> 	; bl = video page number
  4954 00004305 E878220000          <1> 	call 	get_cpos
  4955                              <1> 	; dx = cursor position
  4956 0000430A 66895510            <1> 	mov	[ebp+16], dx ; bx
  4957                              <1> 	;mov	bl, [u.ttyn]
  4958                              <1> 	; bl = video page number
  4959 0000430E E880220000          <1> 	call	read_ac_current
  4960                              <1> 	; ax = character and attribute/color
  4961 00004313 66894518            <1> 	mov	[ebp+24], ax ; cx
  4962 00004317 E9D2F7FFFF          <1> 	jmp	sysret
  4963                              <1> sysgtty_dnr_err:
  4964                              <1> 	; 'device not responding !' error	
  4965                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4966 0000431C C705[1C750000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4966 00004324 0000                <1>
  4967 00004326 E9A3F7FFFF          <1> 	jmp	error	
  4968                              <1> 
  4969                              <1> ; Original UNIX v1 'sysgtty' routine:
  4970                              <1> ; sysgtty:
  4971                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4972                              <1> 	;	       / r2 has destination
  4973                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4974                              <1> 	;                     / in 1st word of dest
  4975                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4976                              <1> 	;                     / in 2nd word of dest
  4977                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4978                              <1>         ;jmp    sysret2 / return to user
  4979                              <1> 	
  4980                              <1> ; Original UNIX v1 'gtty' routine:
  4981                              <1> ; gtty:
  4982                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4983                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4984                              <1>         ;jsr    r0,getf / get the i-number of the file
  4985                              <1>         ;tst    r1 / is it open for reading
  4986                              <1>         ;bgt    1f / yes
  4987                              <1>         ;neg    r1 / no, i-number is negative, 
  4988                              <1> 	;          / so make it positive
  4989                              <1> ;1:
  4990                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4991                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4992                              <1>         ;bhis   error9 / no, error
  4993                              <1>         ;asl    r1 / 0%2
  4994                              <1>         ;asl    r1 / 0%4 / yes
  4995                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4996                              <1> 	;	       ; / tty block
  4997                              <1>         ;mov    u.off,r2 / put argument in r2
  4998                              <1>         ;rts    r0 / return
  2073                                  %include 'u2.s'      ; 11/05/2015
  2074                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2075                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2076                              <1> ; ****************************************************************************
  2077                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS2.INC
  2078                              <1> ; Last Modification: 14/02/2022
  2079                              <1> ; ----------------------------------------------------------------------------
  2080                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2081                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2082                              <1> ;
  2083                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2084                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2085                              <1> ; <Bell Laboratories (17/3/1972)>
  2086                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2087                              <1> ;
  2088                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2089                              <1> ;
  2090                              <1> ; ****************************************************************************
  2091                              <1> 
  2092                              <1> syslink:
  2093                              <1> 	; 12/01/2022
  2094                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2095                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2096                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2097                              <1> 	;
  2098                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2099                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2100                              <1> 	; given to the entry that will go in the current directory.
  2101                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2102                              <1> 	; in the name 2 entry of current directory is the same
  2103                              <1> 	; i-number for the name 1 file.
  2104                              <1> 	;
  2105                              <1> 	; Calling sequence:
  2106                              <1> 	;	syslink; name 1; name 2
  2107                              <1> 	; Arguments:
  2108                              <1> 	;	name 1 - file name to which link will be created.
  2109                              <1> 	;	name 2 - name of entry in current directory that
  2110                              <1> 	;		 links to name 1.
  2111                              <1> 	; Inputs: -
  2112                              <1> 	; Outputs: -
  2113                              <1> 	; ...............................................................
  2114                              <1> 	;	
  2115                              <1> 	; Retro UNIX 8086 v1 modification: 
  2116                              <1> 	;       'syslink' system call has two arguments; so,
  2117                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2118                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2119                              <1> 	;
  2120                              <1> 		; / name1, name2
  2121                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2122 0000432B 891D[C4740000]      <1> 	mov	[u.namep], ebx
  2123 00004331 51                  <1> 	push	ecx
  2124 00004332 E838060000          <1> 	call	namei
  2125                              <1> 		; jsr r0,namei / find the i-number associated with
  2126                              <1> 			     ; / the 1st path name
  2127                              <1>      	;;and	ax, ax
  2128                              <1> 	;;jz	error ; File not found
  2129                              <1> 	;jc	error 
  2130                              <1> 		; br error9 / cannot be found
  2131 00004337 730F                <1> 	jnc	short syslink0
  2132                              <1> 	;pop 	ecx
  2133                              <1> 	; 'file not found !' error
  2134 00004339 C705[1C750000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2134 00004341 0000                <1>
  2135 00004343 E986F7FFFF          <1> 	jmp	error
  2136                              <1> syslink0:
  2137 00004348 E8B7100000          <1> 	call	iget
  2138                              <1> 		; jsr r0,iget / get the i-node into core
  2139 0000434D 8F05[C4740000]      <1> 	pop	dword [u.namep] ; ecx
  2140                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2141                              <1> 	; 24/12/2021
  2142 00004353 50                  <1> 	push	eax ; *
  2143                              <1> 	;push	ax
  2144                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2145                              <1> 			    ; / (a link to this file is to be created)
  2146                              <1> 	; 24/12/2021
  2147 00004354 8A0D[89740000]      <1> 	mov	cl, [cdev]
  2148 0000435A 51                  <1> 	push	ecx ; **
  2149                              <1> 	;push	word [cdev]
  2150                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2151 0000435B E8AC000000          <1> 	call	isdir
  2152                              <1> 		; jsr r0,isdir / is it a directory
  2153 00004360 E80A060000          <1> 	call	namei
  2154                              <1> 		; jsr r0,namei / no, get i-number of name2
  2155                              <1> 	;jnc	error
  2156                              <1> 		; br .+4   / not found 
  2157                              <1> 			 ; / so r1 = i-number of current directory
  2158                              <1> 			 ; / ii = i-number of current directory
  2159                              <1> 		; br error9 / file already exists., error
  2160 00004365 720F                <1> 	jc	short syslink1
  2161                              <1> 	; pop eax ; 24/12/2021
  2162                              <1> 	; pop eax
  2163                              <1> 	; 'file exists !' error
  2164 00004367 C705[1C750000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2164 0000436F 0000                <1>
  2165 00004371 E958F7FFFF          <1> 	jmp	error
  2166                              <1> syslink1:
  2167                              <1> 	;pop	cx
  2168                              <1> 	; 24/12/2021
  2169 00004376 59                  <1> 	pop	ecx ; **
  2170                              <1> 	;cmp	cx, [cdev]
  2171 00004377 3A0D[89740000]      <1> 	cmp	cl, [cdev]
  2172                              <1> 	;jne	error
  2173                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2174                              <1> 			       ; / end of current directory
  2175                              <1> 	        ; bne error9
  2176 0000437D 740F                <1> 	je	short syslink2
  2177                              <1> 	; 'not same drive !' error
  2178 0000437F C705[1C750000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2178 00004387 0000                <1>
  2179 00004389 E940F7FFFF          <1> 	jmp	error
  2180                              <1> syslink2:
  2181                              <1> 	;pop	eax ; 24/12/2021
  2182                              <1> 	;push	eax
  2183                              <1> 	; 24/12/2021
  2184 0000438E 8B0424              <1> 	mov	eax, [esp] ; *
  2185 00004391 66A3[E0740000]      <1> 	mov	[u.dirbuf], ax
  2186                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2187 00004397 E8AD000000          <1> 	call	mkdir
  2188                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2189                              <1> 		 	     ; / in current directory
  2190                              <1> 	; 24/12/2021
  2191 0000439C 58                  <1> 	pop	eax ; *
  2192                              <1> 	;pop	ax
  2193                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2194 0000439D E862100000          <1> 	call	iget
  2195                              <1> 		; jsr r0,iget / get i-node into core
  2196 000043A2 FE05[46700000]      <1> 	inc	byte [i.nlks]
  2197                              <1> 		; incb i.nlks / add 1 to its number of links
  2198                              <1> sysunlink_2:
  2199                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2200 000043A8 C605[9B740000]01    <1> 	mov	byte [imodx], 1	; (flag means file data is same
  2201                              <1> 				;  but inode's itself has been modified)
  2202 000043AF E8EF110000          <1> 	call	setimod
  2203                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2204 000043B4 E935F7FFFF          <1> 	jmp	sysret
  2205                              <1> 
  2206                              <1> sysunlink:
  2207                              <1> 	; 12/01/2022
  2208                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2209                              <1> 	; 04/12/2015 (14 byte file names)
  2210                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2211                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2212                              <1> 	;
  2213                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2214                              <1> 	; name from its directory. If this entry was the last link
  2215                              <1> 	; to the file, the contents of the file are freed and the
  2216                              <1> 	; file is destroyed. If, however, the file was open in any
  2217                              <1> 	; process, the actual destruction is delayed until it is 
  2218                              <1> 	; closed, even though the directory entry has disappeared.
  2219                              <1> 	; 
  2220                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2221                              <1> 	; does not exist or that its directory can not be written.
  2222                              <1> 	; Write permission is not required on the file itself.
  2223                              <1> 	; It is also illegal to unlink a directory (except for
  2224                              <1> 	; the superuser).
  2225                              <1> 	;
  2226                              <1> 	; Calling sequence:
  2227                              <1> 	;	sysunlink; name
  2228                              <1> 	; Arguments:
  2229                              <1> 	;	name - name of directory entry to be removed 
  2230                              <1> 	; Inputs: -
  2231                              <1> 	; Outputs: -
  2232                              <1> 	; ...............................................................
  2233                              <1> 	;				
  2234                              <1> 	; Retro UNIX 8086 v1 modification:
  2235                              <1> 	;	 The user/application program puts address of the name
  2236                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2237                              <1> 
  2238                              <1> 	; / name - remove link name
  2239 000043B9 891D[C4740000]      <1> 	mov	[u.namep], ebx
  2240                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2241 000043BF E8AB050000          <1> 	call	namei
  2242                              <1> 		; jsr r0,namei / find the i-number associated 
  2243                              <1> 			     ; / with the path name
  2244                              <1> 	;jc	error
  2245                              <1> 		; br error9 / not found
  2246 000043C4 730F                <1> 	jnc	short sysunlink1
  2247                              <1> 	; 'file not found !' error
  2248 000043C6 C705[1C750000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2248 000043CE 0000                <1>
  2249 000043D0 E9F9F6FFFF          <1> 	jmp	error
  2250                              <1> sysunlink1:
  2251 000043D5 50                  <1> 	push	eax ; 24/12/2021
  2252                              <1> 	;push	ax
  2253                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2254 000043D6 E831000000          <1> 	call	isdir
  2255                              <1> 		; jsr r0,isdir / is it a directory
  2256                              <1> 	;xor 	ax, ax
  2257                              <1> 	; 24/12/2021
  2258 000043DB 31C0                <1> 	xor	eax, eax
  2259 000043DD 66A3[E0740000]      <1> 	mov	[u.dirbuf], ax ; 0
  2260                              <1> 		; clr u.dirbuf / no, clear the location that will
  2261                              <1> 			   ; / get written into the i-number portion
  2262                              <1> 			 ; / of the entry
  2263 000043E3 832D[C8740000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2264                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2265 000043EA E8A5000000          <1> 	call	wdir
  2266                              <1> 		; jsr r0,wdir / free the directory entry
  2267 000043EF 58                  <1> 	pop	eax ; 24/12/2021
  2268                              <1> 	;pop	ax
  2269                              <1> 		; mov (sp)+,r1 / get i-number back
  2270 000043F0 E80F100000          <1> 	call	iget
  2271                              <1> 		; jsr r0,iget / get i-node
  2272                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2273                              <1> 	;call	setimod
  2274                              <1> 	;	; jsr r0,setimod / set modified flag
  2275                              <1> 	;	
  2276 000043F5 FE0D[46700000]      <1> 	dec	byte [i.nlks]
  2277                              <1> 		; decb i.nlks / decrement the number of links
  2278                              <1> 	; 24/12/2021
  2279 000043FB 75AB                <1> 	jnz	short sysunlink_2
  2280                              <1> 	;jnz	sysret
  2281                              <1> 		; bgt sysret9 / if this was not the last link
  2282                              <1> 			    ; / to file return
  2283                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  2284 000043FD E8A1110000          <1> 	call	setimod
  2285                              <1> 		; jsr r0,setimod / set modified flag
  2286                              <1> 	; AX = r1 = i-number
  2287 00004402 E8340A0000          <1> 	call	anyi
  2288                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2289                              <1> 			 ; / Then free contents of file and destroy it.
  2290 00004407 E9E2F6FFFF          <1> 	jmp	sysret
  2291                              <1> 		; br sysret9
  2292                              <1> ;sysunlink_2:
  2293                              <1> 	;; 12/01/2022 - Retro UNIX 386 v1.2
  2294                              <1> 	;mov	byte [imodx], 1	; (flag means file data is same
  2295                              <1> 	;			;  but inode's itself has been modified)
  2296                              <1> 	;call	setimod
  2297                              <1> 	;	; jsr r0,setimod / set the i-node modified flag
  2298                              <1> 	;jmp	sysret
  2299                              <1> 
  2300                              <1> isdir:
  2301                              <1> 	; 08/01/2022
  2302                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  2303                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2304                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2305                              <1> 	;
  2306                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2307                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2308                              <1> 	;  called by syslink and sysunlink to make sure directories
  2309                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2310                              <1> 	; 'isdir' does not bother checking. The current i-node
  2311                              <1> 	;  is not disturbed.			
  2312                              <1> 	;		
  2313                              <1> 	; INPUTS ->
  2314                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2315                              <1> 	;    u.uid - user id
  2316                              <1> 	; OUTPUTS ->
  2317                              <1> 	;    r1 - contains current i-number upon exit
  2318                              <1> 	;    	 (current i-node back in core) 
  2319                              <1> 	;	
  2320                              <1> 	; ((AX = R1))
  2321                              <1> 	;
  2322                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2323                              <1> 	;
  2324                              <1> 
  2325                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2326                              <1> 	; / there is an error unless super user made the call
  2327                              <1> 	
  2328                              <1> 	; 01/01/2022
  2329 0000440C 66833D[FA740000]00  <1> 	cmp	word [u.uid], 0 ; 16 bit uid (runix v2 fs inode)
  2330                              <1> 	;cmp	byte [u.uid], 0 
  2331                              <1> 		; tstb u.uid / super user
  2332 00004414 7632                <1> 	jna	short isdir1
  2333                              <1> 		; beq 1f / yes, don't care
  2334                              <1> 	; 08/01/2022
  2335 00004416 FF35[84740000]      <1> 	push	dword [ii]
  2336                              <1> 	;push	word [ii]
  2337                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2338 0000441C E8E30F0000          <1> 	call	iget
  2339                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2340                              <1> 	; 01/01/2022 (runix v2 fs inode flags)
  2341 00004421 F605[45700000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  2342 00004428 7409                <1> 	jz	short isdir2 ; no, error!
  2343 0000442A F605[45700000]40    <1> 	test	byte [i.flgs+1], 40h ; directory flag
  2344                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2345                              <1> 		; bit $40000,i.flgs / is it a directory
  2346                              <1> 	;jnz	error
  2347                              <1> 		; bne error9 / yes, error
  2348 00004431 740F                <1> 	jz	short isdir0
  2349                              <1> isdir2:
  2350 00004433 C705[1C750000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2350 0000443B 0000                <1>
  2351                              <1> 				; 'permission denied !' error
  2352                              <1> 	;pop	ax
  2353 0000443D E98CF6FFFF          <1> 	jmp	error	
  2354                              <1> isdir0:	
  2355                              <1> 	; 08/01/2022
  2356 00004442 58                  <1> 	pop	eax
  2357                              <1> 	;pop	ax
  2358                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2359 00004443 E8BC0F0000          <1> 	call	iget
  2360                              <1> 		; jsr r0,iget / get it back in
  2361                              <1> isdir1: ; 1:
  2362 00004448 C3                  <1> 	retn
  2363                              <1> 		; rts r0
  2364                              <1> 
  2365                              <1> mkdir:
  2366                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2367                              <1> 	; 04/12/2015 (14 byte directory names)
  2368                              <1> 	; 12/10/2015
  2369                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2370                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2371                              <1> 	;
  2372                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2373                              <1> 	; by u.namep into the current directory.
  2374                              <1> 	;
  2375                              <1> 	; INPUTS ->
  2376                              <1> 	;    u.namep - points to a file name 
  2377                              <1> 	;	           that is about to be a directory entry.
  2378                              <1> 	;    ii - current directory's i-number.	
  2379                              <1> 	; OUTPUTS ->
  2380                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2381                              <1> 	;    u.off - points to entry to be filled 
  2382                              <1> 	;	     in the current directory		
  2383                              <1> 	;    u.base - points to start of u.dirbuf.
  2384                              <1> 	;    r1 - contains i-number of current directory 
  2385                              <1> 	;	
  2386                              <1> 	; ((AX = R1)) output
  2387                              <1> 	;
  2388                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2389                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2390                              <1> 	;
  2391                              <1> 
  2392                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2393 00004449 31C0                <1> 	xor 	eax, eax
  2394 0000444B BF[E2740000]        <1> 	mov     edi, u.dirbuf+2
  2395 00004450 89FE                <1> 	mov	esi, edi
  2396 00004452 AB                  <1> 	stosd
  2397 00004453 AB                  <1> 	stosd
  2398                              <1> 	; 04/12/2015 (14 byte directory names)
  2399 00004454 AB                  <1> 	stosd
  2400 00004455 66AB                <1> 	stosw
  2401                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2402 00004457 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2403                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2404                              <1> 	;mov 	ebp, [u.namep]
  2405 00004459 E82F060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2406                              <1> 		; esi = physical address (page start + offset)
  2407                              <1> 		; ecx = byte count in the page (1 - 4096)
  2408                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2409                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2410                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2411                              <1> mkdir_1: ; 1: 
  2412 0000445E 45                  <1> 	inc	ebp ; 12/10/2015
  2413                              <1> 	;
  2414                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2415                              <1> 	; 01/08/2013
  2416 0000445F AC                  <1> 	lodsb
  2417                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2418 00004460 20C0                <1> 	and 	al, al
  2419 00004462 7426                <1> 	jz 	short mkdir_3 	  
  2420                              <1> 		; beq 1f / if null, done
  2421 00004464 3C2F                <1> 	cmp	al, '/'
  2422                              <1> 		; cmp r1,$'/ / is it a "/"?
  2423 00004466 7413                <1> 	je	short mkdir_err
  2424                              <1> 	;je	error
  2425                              <1> 		; beq error9 / yes, error
  2426                              <1> 	; 12/10/2015
  2427                              <1> 	;dec	cx
  2428 00004468 49                  <1> 	dec	ecx ; 24/12/2021
  2429 00004469 7505                <1> 	jnz	short mkdir_2
  2430                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2431 0000446B E823060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2432                              <1> 		; esi = physical address (page start + offset)
  2433                              <1> 		; ecx = byte count in the page
  2434                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2435                              <1> mkdir_2:
  2436 00004470 81FF[F0740000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2437                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2438                              <1> 				     ; / a char?
  2439 00004476 74E6                <1> 	je	short mkdir_1
  2440                              <1> 		; beq 1b / yes, go back
  2441 00004478 AA                  <1> 	stosb
  2442                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2443 00004479 EBE3                <1> 	jmp 	short mkdir_1
  2444                              <1> 		; br 1b / get next char
  2445                              <1> mkdir_err:
  2446                              <1> 	; 17/06/2015
  2447 0000447B C705[1C750000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2447 00004483 0000                <1>
  2448 00004485 E944F6FFFF          <1> 	jmp	error
  2449                              <1> 
  2450                              <1> mkdir_3: ; 1:
  2451 0000448A A1[C0740000]        <1> 	mov	eax, [u.dirp]
  2452 0000448F A3[C8740000]        <1> 	mov	[u.off], eax
  2453                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2454                              <1> 				 ; / slot to u.off
  2455                              <1> 	; 08/01/2022
  2456                              <1> wdir:	; 24/12/2021 (Retro UNIX 386 v1.2)
  2457                              <1> 	; 29/04/2013
  2458 00004494 C705[CC740000]-     <1>         mov     dword [u.base], u.dirbuf
  2458 0000449A [E0740000]          <1>
  2459                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2460 0000449E C705[D0740000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2460 000044A6 0000                <1>
  2461                              <1> 		; mov $10.,u.count / u.count = 10
  2462                              <1> 	; 08/01/2022
  2463 000044A8 A1[84740000]        <1> 	mov	eax, [ii]
  2464                              <1> 	;mov	ax, [ii] 
  2465                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2466                              <1> 	;mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2467                              <1> 	; 08/01/2022 (Retro UNIX 386 v2 file system inode)
  2468 000044AD 66BA8000            <1> 	mov	dx, 80h	; mov dx, IWRITE
  2469 000044B1 E838100000          <1> 	call 	access
  2470                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2471                              <1> 				 ; / for writing
  2472                              <1> 	; AX = i-number of current directory
  2473                              <1> 	; 01/08/2013
  2474 000044B6 FE05[1A750000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2475                              <1> 	;call	writei
  2476                              <1> 	;	; jsr r0,writei / write into directory
  2477                              <1> 	;retn	
  2478                              <1> 	;	; rts r0
  2479                              <1> 	; 24/12/2021
  2480 000044BC E9CD140000          <1> 	jmp	writei
  2481                              <1> 
  2482                              <1> 	; 06/02/2022
  2483                              <1> 	; 12/01/2022
  2484                              <1> 	; 01/01/2022
  2485                              <1> 	; 24/12/2021
  2486                              <1> 	; 11/12/2021
  2487                              <1> 	; 04/12/2021
  2488                              <1> 	; 30/11/2021
  2489                              <1> 	; 28/11/2021 - Retro UNIX 386 v1.2
  2490                              <1> 	;	(Retro UNIX 386 v2 fs compatibility modification)
  2491                              <1> sysexec:
  2492                              <1> 	; 02/05/2021
  2493                              <1> 	; 27/03/2021
  2494                              <1> 	; 26/03/2021
  2495                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  2496                              <1> 	; 23/10/2015
  2497                              <1> 	; 10/10/2015, 18/10/2015, 19/10/2015
  2498                              <1> 	; 29/07/2015, 05/08/2015, 05/08/2015
  2499                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2500                              <1> 	; 01/07/2015, 02/07/2015, 20/07,2015
  2501                              <1> 	; 24/06/2015, 25/06/2021
  2502                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2503                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2504                              <1> 	;
  2505                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2506                              <1> 	; pointed to by 'name' in the sysexec call. 
  2507                              <1> 	; 'sysexec' performs the following operations:
  2508                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2509                              <1> 	;    2. obtains i-node of file to be executed via 'iget'.
  2510                              <1> 	;    3. sets trap vectors to system routines.
  2511                              <1> 	;    4. loads arguments to be passed to executing file into
  2512                              <1> 	;	highest locations of user's core
  2513                              <1> 	;    5. puts pointers to arguments in locations immediately
  2514                              <1> 	;	following arguments.
  2515                              <1> 	;    6.	saves number of arguments in next location.
  2516                              <1> 	;    7. initializes user's stack area so that all registers
  2517                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2518                              <1> 	;	to core when 'sysret' restores registers 
  2519                              <1> 	;	and does an rti.
  2520                              <1> 	;    8. inializes u.r0 and u.sp
  2521                              <1> 	;    9. zeros user's core down to u.r0
  2522                              <1> 	;   10.	reads executable file from storage device into core
  2523                              <1> 	;	starting at location 'core'.
  2524                              <1> 	;   11.	sets u.break to point to end of user's code with
  2525                              <1> 	;	data area appended.
  2526                              <1> 	;   12.	calls 'sysret' which returns control at location
  2527                              <1> 	;	'core' via 'rti' instruction.
  2528                              <1> 	;
  2529                              <1> 	; Calling sequence:
  2530                              <1> 	;	sysexec; namep; argp
  2531                              <1> 	; Arguments:
  2532                              <1> 	;	namep - points to pathname of file to be executed
  2533                              <1> 	;	argp  - address of table of argument pointers
  2534                              <1> 	;	argp1... argpn - table of argument pointers
  2535                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2536                              <1> 	; Inputs: (arguments)
  2537                              <1> 	; Outputs: -	
  2538                              <1> 	; ...............................................................
  2539                              <1> 	;
  2540                              <1> 	; Retro UNIX 386 v1 modification: 
  2541                              <1> 	;	User application runs in it's own virtual space 
  2542                              <1> 	;	which is izolated from kernel memory (and other
  2543                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2544                              <1> 	;	privilige mode. Virtual start address is always 0.
  2545                              <1> 	;	User's core memory starts at linear address 400000h
  2546                              <1> 	;	(the end of the 1st 4MB).
  2547                              <1> 	;
  2548                              <1> 	; Retro UNIX 8086 v1 modification: 
  2549                              <1> 	;	user/application segment and system/kernel segment
  2550                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2551                              <1> 	;	are different (user's registers are saved to 
  2552                              <1> 	;	and then restored from system's stack.)
  2553                              <1> 	;
  2554                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2555                              <1> 	;	      arguments which were in these registers;
  2556                              <1> 	;	      but, it returns by putting the 1st argument
  2557                              <1> 	;	      in 'u.namep' and the 2nd argument
  2558                              <1> 	;	      on top of stack. (1st argument is offset of the
  2559                              <1> 	;	      file/path name in the user's program segment.)
  2560                              <1> 	
  2561                              <1> 	;call	arg2
  2562                              <1> 	; * name - 'u.namep' points to address of file/path name
  2563                              <1> 	;          in the user's program segment ('u.segmnt')
  2564                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2565                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2566                              <1> 	;          which is on top of stack.
  2567                              <1> 	;
  2568                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2569                              <1> 
  2570                              <1> 	; 23/06/2015 (32 bit modifications)
  2571                              <1> 
  2572 000044C1 891D[C4740000]      <1> 	mov	[u.namep], ebx ; argument 1
  2573                              <1>         ; 18/10/2015
  2574 000044C7 890D[38750000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2575 000044CD E89D040000          <1> 	call	namei
  2576                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2577                              <1> 			     ; / named in sysexec call in r1
  2578                              <1> 	;jc	error
  2579                              <1> 		; br error9
  2580 000044D2 730F                <1> 	jnc	short sysexec_0
  2581                              <1> 	;
  2582                              <1> 	; 'file not found !' error
  2583 000044D4 C705[1C750000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2583 000044DC 0000                <1>
  2584 000044DE E9EBF5FFFF          <1> 	jmp	error
  2585                              <1> 
  2586                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2587                              <1> 	; (executable file flag is checked in 'access')
  2588                              <1> 	; (following error message is in 'access' subroutine)
  2589                              <1> ;sysexec_not_exf:
  2590                              <1> 	;; 'not executable file !' error
  2591                              <1> 	;mov	dword [u.error], ERR_NOT_EXECUTABLE
  2592                              <1> 	;jmp	error 
  2593                              <1> sysexec_0:
  2594                              <1> 	; 26/03/2021 ('iget' will be called in 'access')
  2595                              <1> 	;call	iget
  2596                              <1> 	;	; jsr r0,iget / get i-node for file to be executed
  2597                              <1> 	;
  2598                              <1> 	;test	byte [i.flgs], 10h
  2599                              <1> 	;;test	word [i.flgs], 10h
  2600                              <1> 	;	; bit $20,i.flgs / is file executable
  2601                              <1> 	;jz	short sysexec_not_exf
  2602                              <1> 	;;jz	error
  2603                              <1> 	;	; beq error9
  2604                              <1> 	; 26/03/2021
  2605 000044E3 66BA4000            <1> 	mov	dx, 40h ; IEXEC - execute, owner
  2606 000044E7 E802100000          <1> 	call	access
  2607                              <1> 	; ! we are here because there is execute permission !
  2608                              <1> 	; ('iopen' is not needed for regular files, from now on)
  2609                              <1> 
  2610                              <1> 	; 26/03/2021
  2611                              <1> 	;; 25/03/2021
  2612                              <1> 	;; (ref: Retro UNIX 386 v2, 'ux.s')
  2613                              <1> 	;mov	dx, 40h ; IEXEC - execute, owner
  2614                              <1> 	;;
  2615                              <1> 	;call	iopen
  2616                              <1> 	;	; jsr r0,iopen / gets i-node for file with i-number
  2617                              <1> 	;		     ; / given in r1 (opens file)
  2618                              <1> 	
  2619                              <1> 	; 26/03/2021
  2620                              <1> 	; AX = i-number of the file
  2621                              <1> 	;test	byte [i.flgs], 20h
  2622                              <1> 	;;test	word [i.flgs], 20h
  2623                              <1> 	;	; bit $40,i.flgs / test user id on execution bit
  2624                              <1> 	;jz	short sysexec_1
  2625                              <1> 	;	; beq 1f
  2626                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013
  2627                              <1> 	;	; tstb u.uid / test user id
  2628                              <1> 	;jna	short sysexec_1
  2629                              <1> 	;	; beq 1f / super user
  2630                              <1> 
  2631                              <1> 	;mov	cl, [i.uid]
  2632                              <1> 	;mov	[u.uid], cl ; 02/08/2013
  2633                              <1> 	;	; movb i.uid,u.uid / put user id of owner of file
  2634                              <1> 				 ; / as process user id
  2635                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2636                              <1> 	;mov	al, [i.flgs+1]
  2637 000044EC 66833D[FA740000]00  <1> 	cmp	word [u.uid], 0	; super user (root) ?
  2638                              <1> 	;jna	short sysexec_19 ; yes, super user
  2639                              <1> 	;; 02/05/2021
  2640 000044F4 7625                <1> 	jna	short sysexec_1	; don't set UID or GID
  2641                              <1> 
  2642                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2
  2643 000044F6 A0[45700000]        <1> 	mov	al, [i.flgs+1]
  2644                              <1> 
  2645                              <1> 	; test set user id on execution bit 
  2646 000044FB A808                <1> 	test	al, 08h ; ISUID flag (800h)
  2647                              <1> 	;jz	short sysexec_19
  2648                              <1> 	; 02/05/2021
  2649 000044FD 741C                <1> 	jz	short sysexec_1 ; do not set group ID
  2650                              <1> 				; (if user ID will not be set)
  2651                              <1> 				; (02/05/2021)	
  2652                              <1> 	; set user id on exec (800h)
  2653                              <1> 	; 26/03/2021
  2654                              <1> sysexec_setuid:
  2655                              <1> 	;; 27/03/2021
  2656                              <1> 	;cmp	word [u.uid], 0
  2657                              <1> 	;;jna	short sysexec_19 ; super user
  2658                              <1> 	;; 02/05/2021
  2659                              <1> 	;jna	short sysexec_1 ; do not set group ID
  2660                              <1> 	;			; (if user ID will not be set)
  2661                              <1> 	;			; (02/05/2021)
  2662 000044FF 668B0D[48700000]    <1> 	mov	cx, [i.uid]
  2663 00004506 66890D[FA740000]    <1> 	mov	[u.uid], cx
  2664                              <1> sysexec_19:
  2665                              <1> 	; test set group id on execution bit 
  2666 0000450D A804                <1> 	test	al, 04h ; ISGID flag (400h)
  2667 0000450F 740A                <1> 	jz	short sysexec_1
  2668                              <1> sysexec_setgid:
  2669                              <1> 	; set group id on exec (400h)
  2670 00004511 A0[4A700000]        <1> 	mov	al, [i.gid]
  2671 00004516 A2[FE740000]        <1> 	mov	[u.gid], al
  2672                              <1> 	;
  2673                              <1> sysexec_1:
  2674                              <1> 	; 06/02/2022
  2675                              <1> 	; 12/01/2022
  2676                              <1> 	; 24/12/2021
  2677                              <1> 	; 11/12/2021
  2678                              <1> 	; 04/12/2021
  2679                              <1> 	; 10/10/2015, 18/10/2015
  2680                              <1> 	; 21/07/2015, 24/07/2015
  2681                              <1> 	; 24/06/2015, 25/06/2015
  2682                              <1>         ; Moving arguments to the end of [u.upage]
  2683                              <1> 	; (by regarding page borders in user's memory space)
  2684                              <1> 	;
  2685                              <1> 	; 10/10/2015
  2686                              <1> 	; 21/07/2015
  2687 0000451B 89E5                <1> 	mov	ebp, esp ; (**)
  2688                              <1> 	; 18/10/2015
  2689 0000451D 89EF                <1> 	mov 	edi, ebp
  2690 0000451F B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2691                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2692 00004524 29CF                <1> 	sub	edi, ecx
  2693 00004526 89FC                <1> 	mov	esp, edi
  2694 00004528 31C0                <1> 	xor	eax, eax
  2695 0000452A A3[D4740000]        <1> 	mov 	[u.nread], eax ; 0
  2696                              <1> 	; 12/01/2022
  2697                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2698                              <1> 	; may leave it with any value after an error))
  2699 0000452F A3[34750000]        <1> 	mov	[argc], eax ; 0
  2700                              <1> 	;
  2701 00004534 49                  <1> 	dec	ecx ; 256 - 1
  2702 00004535 890D[D0740000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2703                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2704                              <1> 	; 24/12/2021
  2705                              <1> sysexec_2:
  2706 0000453B 8B35[38750000]      <1> 	mov	esi, [argv] ; 18/10/2015
  2707 00004541 E859020000          <1> 	call	get_argp
  2708                              <1> 	;mov	ecx, 4 
  2709                              <1> 	; 06/02/2022
  2710 00004546 31C9                <1> 	xor	ecx, ecx
  2711 00004548 B104                <1> 	mov	cl, 4
  2712                              <1> sysexec_3:
  2713 0000454A 21C0                <1> 	and	eax, eax
  2714 0000454C 7454                <1> 	jz	short sysexec_6
  2715                              <1> 	; 18/10/2015
  2716 0000454E 010D[38750000]      <1> 	add	[argv], ecx ; 4
  2717                              <1> 	;;inc	word [argc]
  2718                              <1> 	; 11/12/2021
  2719                              <1> 	;inc	dword [argc]
  2720                              <1> 	; 12/01/2022
  2721 00004554 FE05[34750000]      <1> 	inc	byte [argc]
  2722                              <1> 	;
  2723 0000455A A3[CC740000]        <1> 	mov	[u.base], eax
  2724                              <1>  	; 23/10/2015
  2725 0000455F 66C705[14750000]00- <1> 	mov	word [u.pcount], 0
  2725 00004567 00                  <1>
  2726                              <1> sysexec_4:
  2727 00004568 E8DC150000          <1> 	call	cpass ; get a character from user's core memory
  2728 0000456D 750B                <1>         jnz	short sysexec_5
  2729                              <1> 		; (max. 255 chars + null)
  2730                              <1> 	; 18/10/2015
  2731 0000456F 28C0                <1> 	sub 	al, al
  2732 00004571 AA                  <1> 	stosb
  2733 00004572 FF05[D4740000]      <1> 	inc	dword [u.nread]
  2734 00004578 EB28                <1> 	jmp	short sysexec_6
  2735                              <1> sysexec_5:
  2736 0000457A AA                  <1> 	stosb
  2737 0000457B 20C0                <1> 	and 	al, al
  2738 0000457D 75E9                <1> 	jnz	short sysexec_4
  2739 0000457F B904000000          <1> 	mov	ecx, 4
  2740 00004584 390D[30750000]      <1> 	cmp	[ncount], ecx ; 4
  2741 0000458A 72AF                <1> 	jb	short sysexec_2
  2742 0000458C 8B35[2C750000]      <1> 	mov	esi, [nbase]
  2743 00004592 010D[2C750000]      <1> 	add	[nbase], ecx ; 4	
  2744                              <1> 	;sub	[ncount], cx 
  2745                              <1> 	; 11/12/2021
  2746 00004598 290D[30750000]      <1> 	sub	[ncount], ecx
  2747 0000459E 8B06                <1> 	mov	eax, [esi]
  2748 000045A0 EBA8                <1> 	jmp	short sysexec_3
  2749                              <1> sysexec_6:
  2750                              <1> 	; 24/12/2021
  2751                              <1> 	; 18/10/2015
  2752                              <1> 	; argument list transfer from user's core memory to
  2753                              <1> 	; kernel stack frame is OK here.
  2754                              <1> 	; [u.nread] = argument list length
  2755                              <1> 	;mov	[argv], esp ; start address of argument list
  2756                              <1> 	;
  2757                              <1> 	; 18/10/2015
  2758                              <1> 	; 24/07/2015
  2759                              <1>         ; 21/07/2015
  2760                              <1> 	; 02/07/2015
  2761                              <1> 	; 25/06/2015
  2762                              <1> 	; 24/06/2015
  2763                              <1> 	; 23/06/2015
  2764                              <1> 	;
  2765 000045A2 8B1D[0C750000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2766 000045A8 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2767 000045AA 740A                <1> 	jz	short sysexec_7
  2768 000045AC A1[08750000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2769 000045B1 E820E9FFFF          <1> 	call	deallocate_page_dir
  2770                              <1> sysexec_7:
  2771 000045B6 E850E8FFFF          <1> 	call	make_page_dir
  2772                              <1> 	;jc	short sysexec_14
  2773                              <1> 	;jc	panic  ; allocation error 
  2774                              <1> 	;	       ; after a deallocation would be nonsence !?
  2775                              <1> 	; 26/03/2021
  2776 000045BB 7243                <1> 	jc	short sysexec_panic
  2777                              <1> 	
  2778                              <1> 	; 24/07/2015
  2779                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2780                              <1> 	;     of the user's page directory
  2781                              <1> 	;     (It is needed for interrupts!)
  2782                              <1> 	; 18/10/2015
  2783 000045BD 8B15[886F0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2784 000045C3 8B02                <1> 	mov	eax, [edx] ; physical address of
  2785                              <1> 			   ; kernel's first page table (1st 4 MB)
  2786                              <1> 			   ; (PDE 0 of kernel's page directory)
  2787 000045C5 8B15[08750000]      <1> 	mov 	edx, [u.pgdir]
  2788 000045CB 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2789                              <1> 	;
  2790                              <1> 	; 20/07/2015
  2791 000045CD BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2792                              <1> 	; 18/10/2015
  2793 000045D2 BE[24750000]        <1> 	mov	esi, pcore ; physical start address
  2794                              <1> sysexec_8:	
  2795 000045D7 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2796 000045DC E848E8FFFF          <1> 	call	make_page_table
  2797                              <1> 	;jc	panic
  2798                              <1> 	; 26/03/2021
  2799 000045E1 721D                <1> 	jc	short sysexec_panic
  2800                              <1> 	;
  2801                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2802 000045E3 E84FE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte
  2803                              <1> 	;jc	panic
  2804                              <1> 	; 26/03/2021
  2805 000045E8 7216                <1> 	jc	short sysexec_panic
  2806                              <1> 	;
  2807 000045EA 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2808                              <1> 	; ebx = virtual address (24/07/2015)
  2809                              <1> 	; 30/11/2021
  2810                              <1> 	;call 	add_to_swap_queue
  2811                              <1> 	; 18/10/2015
  2812 000045EC 81FE[28750000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2813 000045F2 7411                <1> 	je	short sysexec_9 ; yes
  2814 000045F4 BE[28750000]        <1> 	mov	esi, ecore  ; physical address of the last page
  2815                              <1> 	; 20/07/2015
  2816 000045F9 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2817                              <1> 	; ebx = virtual end address + segment base address - 4K
  2818 000045FE EBD7                <1>         jmp     short sysexec_8
  2819                              <1> sysexec_panic:
  2820                              <1> 	; 26/03/2021
  2821 00004600 E971EDFFFF          <1> 	jmp	panic
  2822                              <1> 
  2823                              <1> sysexec_9:
  2824                              <1> 	; 12/01/2022
  2825                              <1> 	; 11/12/2021
  2826                              <1> 	; 18/10/2015
  2827                              <1> 	; 26/08/2015
  2828                              <1> 	; 25/06/2015
  2829                              <1> 	; move arguments from kernel stack to [ecore]
  2830                              <1> 	; (argument list/line will be copied from kernel stack
  2831                              <1> 	; frame to the last (stack) page of user's core memory)
  2832                              <1> 	; 18/10/2015
  2833 00004605 8B3D[28750000]      <1> 	mov	edi, [ecore]
  2834 0000460B 81C700100000        <1> 	add	edi, PAGE_SIZE
  2835                              <1> 	;movzx	eax, word [argc]
  2836                              <1> 	; 12/01/2022
  2837                              <1> 	;xor	eax, eax
  2838                              <1> 	;mov	al, [argc]
  2839                              <1> 	; [argc] < 32
  2840                              <1> 	; 11/12/2021
  2841 00004611 A1[34750000]        <1> 	mov	eax, [argc]
  2842 00004616 09C0                <1> 	or	eax, eax
  2843 00004618 7509                <1> 	jnz	short sysexec_10
  2844 0000461A 89FB                <1> 	mov 	ebx, edi
  2845 0000461C 83EB04              <1> 	sub	ebx, 4 
  2846 0000461F 8903                <1> 	mov	[ebx], eax ; 0
  2847 00004621 EB40                <1> 	jmp 	short sysexec_13
  2848                              <1> sysexec_10:
  2849 00004623 8B0D[D4740000]      <1> 	mov	ecx, [u.nread]
  2850                              <1> 	;mov 	esi, [argv]
  2851 00004629 89E6                <1> 	mov	esi, esp ; start address of argument list
  2852 0000462B 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2853 0000462D 89C2                <1> 	mov	edx, eax ; [argc]
  2854 0000462F FEC2                <1> 	inc	dl ; argument count + 1 for argc value  
  2855 00004631 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2856                              <1> 	; max. value of [argc] = 31 (32*4=128)  
  2857                              <1> 	; 12/01/2022
  2858                              <1> 	;inc	edx  ; [argc] <= 255
  2859                              <1> 	;shl	edx, 2 ; max. 256*4
  2860 00004634 89FB                <1> 	mov	ebx, edi
  2861 00004636 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2862 00004639 29D3                <1> 	sub 	ebx, edx
  2863 0000463B 89FA                <1> 	mov	edx, edi
  2864 0000463D F3A4                <1> 	rep	movsb
  2865 0000463F 89D6                <1> 	mov 	esi, edx
  2866 00004641 89DF                <1> 	mov 	edi, ebx
  2867 00004643 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2868 00004648 2B15[28750000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2869 0000464E AB                  <1> 	stosd	; eax = argument count
  2870                              <1> sysexec_11:
  2871 0000464F 89F0                <1> 	mov	eax, esi
  2872 00004651 01D0                <1> 	add	eax, edx
  2873 00004653 AB                  <1> 	stosd  ; eax = virtual address
  2874 00004654 FE0D[34750000]      <1> 	dec	byte [argc]
  2875 0000465A 7407                <1> 	jz	short sysexec_13
  2876                              <1> sysexec_12:
  2877 0000465C AC                  <1> 	lodsb
  2878 0000465D 20C0                <1> 	and	al, al
  2879 0000465F 75FB                <1> 	jnz	short sysexec_12
  2880 00004661 EBEC                <1> 	jmp	short sysexec_11
  2881                              <1> 	;
  2882                              <1> 	; 1:
  2883                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2884                              <1> 			     ; / pointers to arguments to be passed
  2885                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2886                              <1> 			      ; / u.quit = 1 take quit
  2887                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2888                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2889                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2890                              <1> 			       ; / system routine
  2891                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector
  2892                              <1> 			       ; / set to take system routine
  2893                              <1> 		; mov $sstack,sp / stack space used during swapping
  2894                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2895                              <1> 		; mov $ecore,r5 / r5 has end of core
  2896                              <1> 		; mov $core,r4 / r4 has start of users core
  2897                              <1> 		; mov r4,u.base / u.base has start of users core
  2898                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2899                              <1> 	; 1:
  2900                              <1> 		; tst (r2)+ / argument char = "nul"
  2901                              <1> 		; bne 1b
  2902                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of
  2903                              <1> 			  ; / end of argument pointer list
  2904                              <1> 	; 1:
  2905                              <1> 	     ; / move arguments to bottom of users core
  2906                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2907                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2908                              <1> 			    ; / ptr list
  2909                              <1> 		; blo 1f / branch to 1f when all arguments
  2910                              <1> 		       ; / are moved
  2911                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2912                              <1> 	; 2:
  2913                              <1> 		; tstb (r3)+
  2914                              <1> 		; bne 2b / scan argument for \0 (nul)
  2915                              <1> 
  2916                              <1> 	; 2:
  2917                              <1> 		; movb -(r3),-(r5) / move argument char 
  2918                              <1> 				 ; / by char starting at "ecore"
  2919                              <1> 		; cmp r3,(r2) / moved all characters in 
  2920                              <1> 			    ; / this argument
  2921                              <1> 		; bhi 2b / branch 2b if not
  2922                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2923                              <1> 			     ; / r5 has pointer to nth arg
  2924                              <1> 		; br 1b / string
  2925                              <1> 	; 1:
  2926                              <1> 		; clrb -(r5)
  2927                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2928                              <1> 			; / last word of argument strings
  2929                              <1> 		; mov $core,r2
  2930                              <1> 	
  2931                              <1> 	; 1: / move argument pointers into core following 
  2932                              <1> 	      ; / argument strings
  2933                              <1> 		; cmp r2,r4
  2934                              <1> 		; bhis 1f / branch to 1f when all pointers
  2935                              <1> 			; / are moved
  2936                              <1> 		; mov (r2)+,-(r5)
  2937                              <1> 		; br 1b
  2938                              <1> 	; 1:
  2939                              <1> 		; sub $core,r4 / gives number of arguments *2
  2940                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2941                              <1> 		       ; / the number of args stored
  2942                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2943                              <1> 			     ; / of the argument pointers
  2944                              <1> sysexec_13:
  2945                              <1> 	; 30/11/2021
  2946                              <1> 	; 28/11/2021
  2947                              <1> 	; 19/10/2015
  2948                              <1> 	; 18/10/2015
  2949                              <1> 	; 29/07/2015
  2950                              <1> 	; 25/07/2015
  2951                              <1> 	; 24/07/2015
  2952                              <1> 	; 20/07/2015
  2953                              <1> 	; 25/06/2015
  2954                              <1> 	; 24/06/2015
  2955                              <1> 	; 23/06/2015
  2956                              <1> 	;
  2957                              <1> 	; moving arguments to [ecore] is OK here..
  2958                              <1> 	; 18/10/2015
  2959 00004663 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2960                              <1> 	; ebx = beginning address of argument list pointers
  2961                              <1> 	;	in user's stack
  2962                              <1> 	; 19/10/2015
  2963 00004665 2B1D[28750000]      <1> 	sub 	ebx, [ecore]
  2964 0000466B 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2965                              <1> 			; end of core - 4096 (last page)
  2966                              <1> 			; (virtual address)
  2967 00004671 891D[38750000]      <1> 	mov	[argv], ebx
  2968 00004677 891D[D8740000]      <1> 	mov	[u.break], ebx ; available user memory
  2969                              <1> 	;
  2970 0000467D 29C0                <1> 	sub	eax, eax
  2971 0000467F C705[D0740000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2971 00004687 0000                <1>
  2972                              <1> 		; mov $14,u.count
  2973 00004689 C705[BC740000]-     <1> 	mov	dword [u.fofp], u.off
  2973 0000468F [C8740000]          <1>
  2974                              <1> 		; mov $u.off,u.fofp
  2975 00004693 A3[C8740000]        <1> 	mov	[u.off], eax ; 0
  2976                              <1> 		; clr u.off / set offset in file to be read to zero
  2977                              <1> 	; 25/07/2015
  2978 00004698 A3[CC740000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2979                              <1> 	; 25/06/2015 
  2980 0000469D A1[84740000]        <1> 	mov	eax, [ii] ; 28/11/2021 (32 bit inode number)
  2981                              <1> 	; AX = i-number of the executable file
  2982 000046A2 E8D7100000          <1> 	call	readi
  2983                              <1> 		; jsr r0,readi / read in first six words of 
  2984                              <1> 			; / user's file, starting at $core
  2985                              <1> 		; mov sp,r5 / put users stack address in r5
  2986                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2987                              <1> 				; / from r5 (leaves number of words
  2988                              <1> 				; / less 26 available for
  2989                              <1> 			     	; / program in user core
  2990                              <1> 		; mov r5,u.count /
  2991                              <1> 	; 25/06/2015
  2992 000046A7 8B0D[D8740000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2993 000046AD 890D[D0740000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2994                              <1> 	;
  2995 000046B3 8B0D[D4740000]      <1> 	mov	ecx, [u.nread]
  2996 000046B9 890D[D8740000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2997 000046BF 80F920              <1> 	cmp	cl, 32
  2998 000046C2 7540                <1>         jne     short sysexec_15
  2999                              <1> 	;:
  3000                              <1> 	; 25/06/2015
  3001                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  3002                              <1> 	; 18/10/2015
  3003 000046C4 8B35[24750000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  3004                              <1> 		             ; (phys. start addr. of the exec. file)
  3005 000046CA AD                  <1> 	lodsd
  3006 000046CB 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  3007 000046CF 7533                <1> 	jne	short sysexec_15
  3008                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  3009                              <1> 			      ; / if file is standard a.out format
  3010                              <1> 		; bne 1f / branch, if not standard format
  3011 000046D1 AD                  <1> 	lodsd
  3012 000046D2 89C1                <1> 	mov	ecx, eax ; text (code) section size
  3013 000046D4 AD                  <1> 	lodsd
  3014 000046D5 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  3015                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  3016                              <1> 		              ; / number of bytes in program text
  3017                              <1> 		; sub $14,r5 / subtract 12
  3018 000046D7 89CB                <1> 	mov	ebx, ecx
  3019                              <1> 	;
  3020                              <1> 	; 25/06/2015
  3021                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  3022                              <1> 	;	and SINGLIX operating systems (as code template).
  3023                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  3024                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  3025                              <1> 	;	Overrun is not possible for current version.
  3026                              <1> 	;
  3027 000046D9 AD                  <1> 	lodsd	
  3028 000046DA 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  3029 000046DC 3B1D[D0740000]      <1> 	cmp	ebx, [u.count]
  3030 000046E2 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  3031                              <1> 	;
  3032                              <1> 	; 24/07/2015
  3033                              <1> 	; add bss section size to [u.break]
  3034 000046E4 0105[D8740000]      <1> 	add 	[u.break], eax
  3035                              <1> 	;
  3036 000046EA 83E920              <1> 	sub	ecx, 32 ; header size (already loaded)
  3037                              <1> 	;cmp	ecx, [u.count]
  3038                              <1> 	;jnb	short sysexec_16
  3039                              <1> 		; cmp r5,u.count /
  3040                              <1> 		; bgt 1f / branch if r5 greater than u.count
  3041 000046ED 890D[D0740000]      <1> 	mov	[u.count], ecx ; required read count
  3042                              <1> 		; mov r5,u.count
  3043                              <1> 	;
  3044 000046F3 EB29                <1> 	jmp	short sysexec_16
  3045                              <1> 	;
  3046                              <1> sysexec_14:
  3047                              <1> 	; 23/06/2015
  3048                              <1> 	; insufficient (out of) memory
  3049 000046F5 C705[1C750000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  3049 000046FD 0000                <1>
  3050 000046FF E9CAF3FFFF          <1> 	jmp	error
  3051                              <1> 	;
  3052                              <1> sysexec_15:
  3053                              <1> 	; 25/06/2015
  3054                              <1>         ;movzx   edx, word [i.size] ; file size
  3055                              <1> 	; 30/11/2021
  3056 00004704 8B15[4C700000]      <1> 	mov	edx, [i.size] ; file size
  3057 0000470A 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  3058 0000470C 7626                <1> 	jna	short sysexec_17 ; no need to next read
  3059 0000470E 01D1                <1> 	add	ecx, edx ; [i.size]
  3060 00004710 3B0D[D0740000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  3061 00004716 77DD                <1> 	ja	short sysexec_14
  3062 00004718 8915[D0740000]      <1> 	mov	[u.count], edx
  3063                              <1> sysexec_16:
  3064                              <1> 	;mov	ax, [ii] ; i-number
  3065                              <1> 	; 28/11/2021
  3066 0000471E A1[84740000]        <1> 	mov	eax, [ii] ; 32 bit inode number
  3067 00004723 E856100000          <1> 	call	readi
  3068                              <1> 		; add core+10,u.nread / add size of user data area
  3069                              <1> 		                    ; / to u.nread
  3070                              <1> 		; br 2f
  3071                              <1> 	; 1:
  3072                              <1> 		; jsr r0,readi / read in rest of file
  3073                              <1> 	; 2:
  3074 00004728 8B0D[D4740000]      <1> 	mov	ecx, [u.nread]
  3075 0000472E 010D[D8740000]      <1> 	add	[u.break], ecx
  3076                              <1> 		; mov u.nread,u.break / set users program break to end of
  3077                              <1> 				    ; / user code
  3078                              <1> 		; add $core+14,u.break / plus data area
  3079                              <1> 	; 20/07/2015
  3080                              <1> sysexec_17:
  3081                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  3082                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3083                              <1> 	;;mov	ax, [ii] ; i-number
  3084                              <1> 	;call	iclose
  3085                              <1> 	;	; jsr r0,iclose / does nothing
  3086 00004734 31C0                <1>         xor     eax, eax
  3087 00004736 FEC0                <1> 	inc	al
  3088 00004738 66A3[F4740000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3089 0000473E 66A3[F6740000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3090                              <1> 	; 30/11/2021
  3091 00004744 FEC8                <1> 	dec	al  ; eax = 0
  3092                              <1> 	; 02/07/2015
  3093                              <1>         ;cmp	dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ?
  3094 00004746 3905[0C750000]      <1> 	cmp	[u.ppgdir], eax ; 0 ; is the caller sys_init (kernel) ?
  3095 0000474C 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3096                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3097 0000474E 8B15[886F0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3098 00004754 8915[0C750000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here
  3099                              <1> sysexec_18:
  3100                              <1> 	; 18/10/2015
  3101                              <1> 	; 05/08/2015
  3102                              <1> 	; 29/07/2015
  3103 0000475A 8B2D[38750000]      <1> 	mov	ebp, [argv] ; user's stack pointer must points to argument
  3104                              <1> 			    ; list pointers (argument count)
  3105 00004760 FA                  <1> 	cli
  3106 00004761 8B25[246F0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3107                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3108                              <1> 			    ; for this process	 
  3109                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3110                              <1> 	;;xor	eax, eax ; 0
  3111                              <1> 	;dec	al ; eax = 0
  3112                              <1> 	; eax = 0 ; 30/11/2021 
  3113 00004767 66BA2300            <1> 	mov	dx, UDATA
  3114 0000476B 6652                <1> 	push	dx  ; user's stack segment
  3115 0000476D 55                  <1> 	push	ebp ; user's stack pointer
  3116                              <1> 		    ; (points to number of arguments)
  3117 0000476E FB                  <1> 	sti
  3118 0000476F 9C                  <1> 	pushfd	; EFLAGS
  3119                              <1> 		; Set IF for enabling interrupts in user mode
  3120                              <1> 	;or	dword [esp], 200h 
  3121                              <1> 	;
  3122                              <1> 	;mov	bx, UCODE
  3123                              <1> 	;push	bx ; user's code segment
  3124 00004770 6A1B                <1> 	push	UCODE
  3125                              <1> 	;push	0
  3126 00004772 50                  <1> 	push	eax ; EIP (=0) - start address -
  3127                              <1> 		; clr -(r5) / popped into ps when rti in 
  3128                              <1> 			  ; / sysrele is executed
  3129                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3130                              <1> 		                ; / in sysrele is executed
  3131                              <1> 		;mov r5,0f / load second copyz argument
  3132                              <1> 		;tst -(r5) / decrement r5
  3133 00004773 8925[A0740000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3134                              <1> 	; 05/08/2015
  3135                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3136                              <1> 	; ('push dx' would cause to general protection fault, 
  3137                              <1> 	; after 'pop ds' etc.)
  3138                              <1> 	;
  3139                              <1> 	;; push dx ; ds (UDATA)
  3140                              <1> 	;; push dx ; es (UDATA)
  3141                              <1> 	;; push dx ; fs (UDATA)
  3142                              <1> 	;; push dx ; gs (UDATA)
  3143                              <1> 	;
  3144                              <1> 	; This is a trick to prevent general protection fault
  3145                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3146 00004779 8EC2                <1> 	mov 	es, dx ; UDATA
  3147 0000477B 06                  <1> 	push 	es ; ds (UDATA)
  3148 0000477C 06                  <1> 	push 	es ; es (UDATA)
  3149 0000477D 06                  <1> 	push 	es ; fs (UDATA)
  3150 0000477E 06                  <1> 	push	es ; gs (UDATA)
  3151 0000477F 66BA1000            <1> 	mov	dx, KDATA
  3152 00004783 8EC2                <1> 	mov	es, dx
  3153                              <1> 	;
  3154                              <1> 	;; pushad simulation
  3155 00004785 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3156 00004787 50                  <1> 	push	eax ; eax (0)
  3157 00004788 50                  <1> 	push	eax ; ecx (0)
  3158 00004789 50                  <1> 	push	eax ; edx (0)
  3159 0000478A 50                  <1> 	push	eax ; ebx (0)
  3160 0000478B 55                  <1> 	push	ebp ; esp before pushad
  3161 0000478C 50                  <1> 	push	eax ; ebp (0)
  3162 0000478D 50                  <1> 	push	eax ; esi (0)		
  3163 0000478E 50                  <1> 	push	eax ; edi (0)	
  3164                              <1> 	;
  3165 0000478F A3[A8740000]        <1> 	mov	[u.r0], eax ; eax = 0
  3166 00004794 8925[A4740000]      <1> 	mov	[u.usp], esp
  3167                              <1> 		; mov r5,u.r0 /
  3168                              <1> 		; sub $16.,r5 / skip 8 words
  3169                              <1> 		; mov r5,u.sp / assign user stack pointer value,
  3170                              <1> 		;             / effectively zeroes all regs
  3171                              <1> 			    ; / when sysrele is executed
  3172                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3173                              <1> 		; clr u.break
  3174                              <1> 		; mov r5,sp / point sp to user's stack
  3175                              <1> 	;
  3176 0000479A E951F3FFFF          <1> 	jmp	sysret0
  3177                              <1> 	;jmp	sysret
  3178                              <1> 		; br sysret3 / return to core image at $core
  3179                              <1> 
  3180                              <1> get_argp:
  3181                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  3182                              <1> 	; 18/10/2015 (nbase, ncount)
  3183                              <1> 	; 21/07/2015
  3184                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3185                              <1> 	; Get (virtual) address of argument from user's core memory
  3186                              <1> 	;
  3187                              <1> 	; INPUT:
  3188                              <1> 	;	esi = virtual address of argument pointer
  3189                              <1> 	; OUTPUT:
  3190                              <1> 	;	eax = virtual address of argument
  3191                              <1> 	;
  3192                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3193                              <1> 	;
  3194 0000479F 833D[0C750000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3195                              <1> 				    ; (the caller is kernel)
  3196 000047A6 767C                <1>         jna     short get_argpk 
  3197                              <1> 	;
  3198 000047A8 89F3                <1>      	mov	ebx, esi
  3199 000047AA E8E3E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3200 000047AF 7254                <1>         jc	short get_argp_err ; 11/12/2021
  3201 000047B1 A3[2C750000]        <1> 	mov 	[nbase], eax ; physical address	
  3202                              <1> 	;mov	[ncount], cx ; remain byte count in page (1-4096)
  3203                              <1> 	; 11/12/2021
  3204 000047B6 890D[30750000]      <1> 	mov	[ncount], ecx
  3205 000047BC B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3206                              <1> 	;cmp	cx, ax ; 4
  3207                              <1> 	; 11/12/2021
  3208 000047C1 39C1                <1> 	cmp	ecx, eax ; 4
  3209 000047C3 734A                <1> 	jnb	short get_argp2
  3210 000047C5 89F3                <1> 	mov	ebx, esi
  3211 000047C7 01CB                <1> 	add	ebx, ecx
  3212 000047C9 E8C4E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3213 000047CE 7235                <1> 	jc	short get_argp_err
  3214                              <1> 	;push	esi
  3215 000047D0 89C6                <1> 	mov	esi, eax
  3216                              <1> 	;xchg	cx, [ncount]
  3217                              <1> 	; 11/12/2021
  3218 000047D2 870D[30750000]      <1> 	xchg	ecx, [ncount]
  3219 000047D8 8735[2C750000]      <1> 	xchg	esi, [nbase]
  3220 000047DE B504                <1> 	mov	ch, 4
  3221 000047E0 28CD                <1> 	sub	ch, cl
  3222                              <1> get_argp0:
  3223 000047E2 AC                  <1> 	lodsb
  3224                              <1> 	;push	ax
  3225                              <1> 	; 11/12/2021
  3226 000047E3 50                  <1> 	push	eax
  3227 000047E4 FEC9                <1> 	dec	cl
  3228 000047E6 75FA                <1>         jnz     short get_argp0
  3229 000047E8 8B35[2C750000]      <1> 	mov	esi, [nbase]
  3230                              <1> 	; 21/07/2015
  3231 000047EE 0FB6C5              <1> 	movzx	eax, ch
  3232 000047F1 0105[2C750000]      <1> 	add	[nbase], eax
  3233                              <1> 	;sub	[ncount], ax
  3234                              <1> 	; 11/12/2021
  3235 000047F7 2905[30750000]      <1> 	sub	[ncount], eax
  3236                              <1> get_argp1:
  3237 000047FD AC                  <1> 	lodsb
  3238 000047FE FECD                <1> 	dec	ch
  3239 00004800 743B                <1>         jz      short get_argp3
  3240                              <1>         ;push	ax
  3241                              <1> 	; 11/12/2021
  3242 00004802 50                  <1> 	push	eax
  3243 00004803 EBF8                <1> 	jmp     short get_argp1
  3244                              <1> get_argp_err:
  3245 00004805 A3[1C750000]        <1> 	mov	[u.error], eax
  3246 0000480A E9BFF2FFFF          <1> 	jmp	error
  3247                              <1> get_argp2:
  3248                              <1> 	; 21/07/2015
  3249                              <1> 	;mov	eax, 4
  3250 0000480F 8B15[2C750000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3251 00004815 0105[2C750000]      <1> 	add	[nbase], eax
  3252                              <1> 	;sub	[ncount], ax
  3253                              <1> 	; 11/12/2021
  3254 0000481B 2905[30750000]      <1> 	sub	[ncount], eax
  3255                              <1> 	;
  3256 00004821 8B02                <1> 	mov	eax, [edx]
  3257 00004823 C3                  <1> 	retn
  3258                              <1> get_argpk:
  3259                              <1> 	; Argument is in kernel's memory space
  3260 00004824 66C705[30750000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3260 0000482C 10                  <1>
  3261 0000482D 8935[2C750000]      <1> 	mov	[nbase], esi
  3262 00004833 8305[2C750000]04    <1> 	add	dword [nbase], 4
  3263 0000483A 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physical addr.
  3264 0000483C C3                  <1> 	retn
  3265                              <1> get_argp3:
  3266 0000483D B103                <1> 	mov	cl, 3
  3267                              <1> get_argp4:
  3268 0000483F C1E008              <1> 	shl	eax, 8
  3269                              <1> 	;pop	dx
  3270                              <1> 	; 11/12/2021
  3271 00004842 5A                  <1> 	pop	edx
  3272 00004843 88D0                <1> 	mov 	al, dl
  3273 00004845 E2F8                <1>         loop    get_argp4
  3274                              <1> 	;pop	esi
  3275 00004847 C3                  <1> 	retn	
  3276                              <1> 
  3277                              <1> sysfstat:
  3278                              <1> 	; 06/02/2022 
  3279                              <1> 	; 08/01/2022
  3280                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3281                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3282                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3283                              <1> 	;
  3284                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3285                              <1> 	; on open files instead of files given by name. It puts the
  3286                              <1> 	; buffer address on the stack, gets the i-number and
  3287                              <1> 	; checks to see if the file is open for reading or writing.
  3288                              <1> 	; If the file is open for writing (i-number is negative)
  3289                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3290                              <1> 	; is made.	
  3291                              <1> 	;
  3292                              <1> 	; Calling sequence:
  3293                              <1> 	;	sysfstat; buf
  3294                              <1> 	; Arguments:
  3295                              <1> 	;	buf - buffer address
  3296                              <1> 	;
  3297                              <1> 	; Inputs: *u.r0 - file descriptor
  3298                              <1> 	; Outputs: buffer is loaded with file information
  3299                              <1> 	; ...............................................................
  3300                              <1> 	;				
  3301                              <1> 	; Retro UNIX 8086 v1 modification:
  3302                              <1> 	;       'sysfstat' system call has two arguments; so,
  3303                              <1> 	;	* 1st argument, file descriptor is in BX register
  3304                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3305                              <1> 
  3306                              <1> 	; / set status of open file
  3307                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3308 00004848 51                  <1> 	push	ecx ; *
  3309                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3310                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3311                              <1> 		; jsr r0,getf / get the files i-number
  3312                              <1> 	; BX = file descriptor (file number)
  3313 00004849 E8EB000000          <1> 	call	getf1
  3314                              <1> 	; 06/02/2022
  3315 0000484E 21C0                <1> 	and	eax, eax
  3316                              <1> 	;and	ax, ax ; i-number of the file
  3317                              <1> 		; tst	r1 / is it 0?
  3318                              <1> 	;jz	error
  3319                              <1> 		; beq error3 / yes, error
  3320                              <1> 	;jnz	short sysfstat1
  3321                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2 (runix v2 file system)
  3322 00004850 752C                <1> 	jnz	short sysstat1
  3323 00004852 C705[1C750000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3323 0000485A 0000                <1>
  3324 0000485C E96DF2FFFF          <1> 	jmp	error
  3325                              <1> 	; 26/12/2021
  3326                              <1> ;sysfstat1:
  3327                              <1> 	;cmp	ah, 80h
  3328                              <1>         ;jb      short sysstat1
  3329                              <1> 	;	; bgt 1f / if i-number is negative (open for writing)
  3330                              <1> 	;neg	ax
  3331                              <1> 	;	; neg r1 / make it positive, then branch
  3332                              <1> 	; 08/01/2022
  3333                              <1> 	;jmp	short sysstat1
  3334                              <1> 		; br 1f / to 1f
  3335                              <1> sysstat:
  3336                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3337                              <1> 	; 18/10/2015
  3338                              <1> 	; 07/10/2015
  3339                              <1> 	; 02/09/2015
  3340                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3341                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3342                              <1> 	;
  3343                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3344                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3345                              <1> 	; long and information about the file placed in it.	
  3346                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3347                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3348                              <1> 	; is then loaded and the results are given in the UNIX
  3349                              <1> 	; Programmers Manual sysstat (II).	
  3350                              <1> 	;
  3351                              <1> 	; Calling sequence:
  3352                              <1> 	;	sysstat; name; buf
  3353                              <1> 	; Arguments:
  3354                              <1> 	;	name - points to the name of the file
  3355                              <1> 	;	buf - address of a 34 bytes buffer
  3356                              <1> 	; Inputs: -
  3357                              <1> 	; Outputs: buffer is loaded with file information
  3358                              <1> 	; ...............................................................
  3359                              <1> 	;				
  3360                              <1> 	; Retro UNIX 8086 v1 modification: 
  3361                              <1> 	;       'sysstat' system call has two arguments; so,
  3362                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3363                              <1> 	;	to get sysstat system call arguments from the user;
  3364                              <1> 	;	* 1st argument, name is pointed to by BX register
  3365                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3366                              <1> 	;
  3367                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3368                              <1> 	;	      arguments which were in these registers;
  3369                              <1> 	;	      but, it returns by putting the 1st argument
  3370                              <1> 	;	      in 'u.namep' and the 2nd argument
  3371                              <1> 	;	      on top of stack. (1st argument is offset of the
  3372                              <1> 	;	      file/path name in the user's program segment.)		 	
  3373                              <1> 	
  3374                              <1> 	; / ; name of file; buffer - get files status
  3375                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3376 00004861 891D[C4740000]      <1> 	mov	[u.namep], ebx
  3377 00004867 51                  <1> 	push	ecx ; *
  3378 00004868 E802010000          <1> 	call	namei
  3379                              <1> 		; jsr r0,namei / get the i-number for the file
  3380                              <1> 	;jc	error
  3381                              <1> 		; br error3 / no such file, error
  3382 0000486D 730F                <1> 	jnc	short sysstat1
  3383                              <1> 	; pop 	ecx
  3384                              <1> sysstat_err0:
  3385                              <1> 	; 'file not found !' error
  3386 0000486F C705[1C750000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3386 00004877 0000                <1>
  3387 00004879 E950F2FFFF          <1> 	jmp	error
  3388                              <1> 
  3389                              <1> sysstat1: ; 1:
  3390 0000487E E8810B0000          <1> 	call	iget
  3391                              <1> 		; jsr r0,iget / get the i-node into core
  3392                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3393                              <1> 	; 02/09/2015
  3394 00004883 8F05[CC740000]      <1> 	pop	dword [u.base] ; *
  3395                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3396 00004889 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3397 0000488E 730A                <1> 	jnc 	short sysstat2
  3398                              <1> sysstat_err1:
  3399 00004890 A3[1C750000]        <1> 	mov	dword [u.error], eax ; error code
  3400 00004895 E934F2FFFF          <1> 	jmp	error
  3401                              <1> sysstat2:
  3402 0000489A A0[84740000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3403 0000489F AA                  <1> 	stosb
  3404 000048A0 FF05[CC740000]      <1> 	inc 	dword [u.base]
  3405                              <1> 	;dec 	cx
  3406 000048A6 49                  <1> 	dec	ecx ; 26/12/2021
  3407 000048A7 7505                <1> 	jnz	short sysstat3
  3408 000048A9 E835000000          <1> 	call	sysstat_gpa
  3409                              <1> 	;jc	short sysstat_err1
  3410                              <1> sysstat3:
  3411 000048AE A0[85740000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3412 000048B3 AA                  <1> 	stosb
  3413                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3414 000048B4 FF05[CC740000]      <1> 	inc 	dword [u.base]
  3415                              <1> 	;;dec 	word [u.pcount]
  3416                              <1> 	;dec	cx
  3417 000048BA 49                  <1> 	dec	ecx ; 26/12/2021
  3418 000048BB 7505                <1> 	jnz	short sysstat4
  3419 000048BD E821000000          <1> 	call	sysstat_gpa
  3420                              <1> 	;jc	short sysstat_err1	
  3421                              <1> sysstat4:
  3422 000048C2 BE[44700000]        <1> 	mov	esi, inode
  3423                              <1> 		; mov $inode,r2 / r2 points to i-node
  3424                              <1> sysstat5: ; 1:
  3425 000048C7 A4                  <1> 	movsb
  3426                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3427 000048C8 FF05[CC740000]      <1> 	inc 	dword [u.base]
  3428                              <1> 	;;dec 	word [u.pcount]
  3429                              <1> 	;dec	cx
  3430 000048CE 49                  <1> 	dec	ecx ; 26/12/2021
  3431 000048CF 7505                <1> 	jnz	short sysstat6
  3432 000048D1 E80D000000          <1> 	call	sysstat_gpa
  3433                              <1> 	;jc	short sysstat_err1
  3434                              <1> sysstat6:
  3435                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2
  3436 000048D6 81FE[84700000]      <1> 	cmp	esi, inode + 64 ; Retro UNIX v2 inode		
  3437                              <1> 	;cmp	esi, inode + 32
  3438                              <1> 		; cmp r2,$inode+32 / done?
  3439 000048DC 75E9                <1> 	jne	short sysstat5
  3440                              <1> 		; bne 1b / no, go back
  3441 000048DE E90BF2FFFF          <1> 	jmp	sysret
  3442                              <1> 		; br sysret3 / return through sysret
  3443                              <1> 	;
  3444                              <1> sysstat_gpa: ; get physical address of file status buffer
  3445                              <1> 	; 02/09/2015
  3446 000048E3 8B1D[CC740000]      <1> 	mov 	ebx, [u.base]
  3447                              <1> 	; 07/10/2015
  3448 000048E9 E8A4E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3449                              <1> 	;jc	short sysstat_gpa1
  3450 000048EE 72A0                <1> 	jc	short sysstat_err1
  3451                              <1> 	; 18/10/2015
  3452 000048F0 89C7                <1> 	mov	edi, eax ; physical address
  3453                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3454                              <1> ;sysstat_gpa1:
  3455 000048F2 C3                  <1> 	retn
  3456                              <1> 
  3457                              <1> fclose:
  3458                              <1> 	; 11/02/2022
  3459                              <1> 	; 08/01/2022
  3460                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3461                              <1> 	; 08/04/2021
  3462                              <1> 	; 04/04/2021
  3463                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3464                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3465                              <1> 	;            (32 bit offset pointer modification)
  3466                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3467                              <1> 	;
  3468                              <1> 	; Given the file descriptor (index to the u.fp list)
  3469                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3470                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3471                              <1> 	; u.fp list is cleared. If all the processes that opened
  3472                              <1> 	; that file close it, then fsp etry is freed and the file
  3473                              <1> 	; is closed. If not a return is taken. 
  3474                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3475                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3476                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3477                              <1> 	; a check is made to see if the file is special.	
  3478                              <1> 	;
  3479                              <1> 	; INPUTS ->
  3480                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3481                              <1> 	;    u.fp - list of entries in the fsp table
  3482                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3483                              <1> 	; OUTPUTS ->
  3484                              <1> 	;    r1 - contains the same file descriptor
  3485                              <1> 	;    r2 - contains i-number
  3486                              <1> 	;
  3487                              <1> 	; ((AX = R1))
  3488                              <1> 	; ((Modified registers: edx, ebx, ecx, esi, edi, ebp))
  3489                              <1> 	;
  3490                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3491                              <1> 	;              if i-number of the file is 0. (error)
  3492                              <1> 
  3493                              <1> 	; 08/04/2021
  3494                              <1> 	; INPUT:
  3495                              <1> 	;	eax = file descriptor
  3496                              <1> 	; OUTPUT:
  3497                              <1> 	;	cf = 0 -> eax = file descriptor
  3498                              <1> 	;	cf = 1 -> file not open ; 11/02/2022
  3499                              <1> 
  3500                              <1> 	; 18/08/2020
  3501                              <1> 	;movzx	edx, ax ; **
  3502 000048F3 89C3                <1> 	mov	ebx, eax
  3503                              <1> 
  3504                              <1> 	; 18/08/2020
  3505                              <1> _fclose:
  3506 000048F5 53                  <1> 	push	ebx ; ***  ; file descriptor (index to u.fp)
  3507                              <1> 
  3508                              <1> 	;push	ax ; ***
  3509                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3510                              <1> 			     ; / the index to u.fp list)
  3511                              <1> 	; ebx = file descriptor/number
  3512 000048F6 E83E000000          <1> 	call	getf
  3513                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3514                              <1> 			    ; / cdev has device =, u.fofp 
  3515                              <1> 			    ; / points to 3rd word of fsp entry
  3516                              <1> 	;cmp	eax, 1 ; 18/08/2020
  3517 000048FB 6683F801            <1> 	cmp	ax, 1 ; r1
  3518                              <1> 		; tst r1 / is i-number 0?
  3519 000048FF 7236                <1> 	jb	short fclose_2
  3520                              <1> 		; beq 1f / yes, i-node not active so return
  3521                              <1> 		; tst (r0)+ / no, jump over error return
  3522                              <1> 	
  3523                              <1> 	;mov	ebx, edx ; **
  3524                              <1>  	; 18/08/2020
  3525 00004901 8B1C24              <1> 	mov	ebx, [esp]
  3526                              <1> 	;mov	edx, eax 
  3527                              <1> 	;;mov 	dx, ax ; *
  3528                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3529                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3530                              <1> 			    ; / which is index to u.fp ; **
  3531 00004904 C683[B2740000]00    <1> 	mov	byte [ebx+u.fp], 0
  3532                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3533 0000490B 8B1D[BC740000]      <1> 	mov	ebx, [u.fofp]
  3534                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3535                              <1> 
  3536                              <1> 	; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3537                              <1> 	; ebx = 5th word of fsp entry (64 bit file offset)
  3538                              <1> fclose_0:
  3539                              <1> 	; 08/01/2022
  3540 00004911 FE4BFE              <1> 	dec	byte [ebx-2] ; 18/08/2020 - Retro UNIX 386 v2
  3541                              <1> 	;dec	byte [ebx+4] ; 18/06/2015
  3542                              <1> 		; decb 2(r1) / decrement the number of processes 
  3543                              <1> 			   ; / that have opened the file
  3544 00004914 7921                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3545                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3546                              <1> 	;
  3547                              <1> 	;push	dx ; *
  3548                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3549                              <1> 	;;xor	ax, ax ; 0
  3550                              <1> 	;xor	eax, eax ; 18/08/2020
  3551                              <1> 		; clear 1st word of fsp entry
  3552                              <1> 	;mov	[ebx-8], ax ; 0 ; 18/08/2020
  3553                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3554 00004916 66C743F80000        <1> 	mov	word [ebx-8], 0 ; clear 1st word of fsp entry ; i-number
  3555                              <1> 			; Note: 32 bit i-node number field is ready but
  3556                              <1> 			;	it is not used in current runix version.	
  3557                              <1> 
  3558                              <1> 	;;mov	[ebx-4], ax ; 0
  3559                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3560                              <1> 	;mov	al, [ebx+5] ; 18/06/2015
  3561                              <1> 	;	; tstb	3(r1) / has this file been deleted
  3562                              <1> 	;and	al, al
  3563                              <1> 	;jz	short fclose_1
  3564                              <1> 	;	; beq 2f / no, branch
  3565                              <1> 
  3566                              <1> 	;push	edx ; * ; 18/08/2020
  3567                              <1> 	;mov	eax, edx ; * ; 18/08/2020
  3568                              <1> 
  3569                              <1> 	;; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3570                              <1> 	;;test	byte [ebx-3], 80h ; open mode & status flags
  3571                              <1> 	; 04/04/2021 - Retro UNIX 386 v2 (new fsp structure)
  3572                              <1> 	;test	byte [ebx-4], 80h ; open mode & status flags 
  3573                              <1> 	;jz	short fclose_1	; deleted file flag (bit 7)
  3574                              <1> 
  3575                              <1> 	; 04/04/2021
  3576 0000491C 31D2                <1> 	xor	edx, edx
  3577                              <1> 	; 08/01/2022
  3578 0000491E 8A53FD              <1> 	mov	dl, [ebx-3] ; open mode & status flags
  3579 00004921 F6C280              <1> 	test	dl, 80h	    ; deleted file flag (bit 7)
  3580 00004924 7407                <1> 	jz	short fclose_1 ; (not deleted -while open-)
  3581 00004926 52                  <1> 	push	edx
  3582                              <1> 
  3583                              <1> 	; deleted file !
  3584                              <1> 
  3585                              <1> 	;mov	ax, dx ; *
  3586                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3587                              <1> 	; AX = inode number
  3588 00004927 E80F050000          <1> 	call	anyi
  3589                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3590                              <1> 			    ; / check if file appears in fsp again
  3591                              <1> 	; 04/04/2021
  3592 0000492C 5A                  <1> 	pop	edx
  3593                              <1> 	; 11/02/2022
  3594                              <1> 	;(cpu will come here if anyi returns -without error-)
  3595                              <1> 	;; 08/04/2021
  3596                              <1> 	;jc	short fclose_3 ; error code in eax	
  3597                              <1> 	;; 18/08/2020
  3598                              <1> 	;;jmp	short fclose_2
  3599                              <1> 
  3600                              <1> 	; ax = inode number
  3601                              <1> fclose_1: ; 2:
  3602                              <1> 	; 04/04/2021
  3603 0000492D 80E201              <1> 	and	dl, 1
  3604 00004930 FEC2                <1> 	inc	dl ; 0 -> 1 (open for read), 1 -> 2 (open for write)
  3605                              <1> 	
  3606                              <1> 	;pop	eax ; * ; 18/08/2020 
  3607                              <1> 	;;pop	ax ; *
  3608                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3609 00004932 E8A9150000          <1> 	call	iclose ; close if it is special file 
  3610                              <1> 		; jsr r0,iclose / check to see if it is a special file
  3611                              <1> 	; 11/02/2022
  3612                              <1> 	;(cpu will come here if iclose returns -without error-)
  3613                              <1> 	;; 08/04/2021
  3614                              <1> 	;jnc	short fclose_2
  3615                              <1> ;fclose_3:
  3616                              <1> ;	pop	ebx ; ***  ; file descriptor
  3617                              <1> ;	; eax = error code
  3618                              <1> ;	retn
  3619                              <1> fclose_2: ; 1:
  3620 00004937 58                  <1> 	pop	eax ; *** ; 18/08/2020
  3621                              <1> 	;pop	ax ; ***
  3622                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3623 00004938 C3                  <1> 	retn
  3624                              <1> 		; rts r0
  3625                              <1> 
  3626                              <1> 	; 08/01/2022
  3627                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3628                              <1> getf:	; / get the device number and the i-number of an open file
  3629                              <1> 	; 13/05/2015
  3630                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3631                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3632                              <1> 
  3633                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3634                              <1> 	;
  3635                              <1> 	; 16/05/2021
  3636                              <1> 	; 27/03/2020 - Retro UNIX 386 v2 
  3637                              <1> 	;	(new open files -fsp- structure)
  3638                              <1> 	; 13/05/2015
  3639                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3640                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3641                              <1> 	
  3642                              <1> 	; INPUT: 
  3643                              <1> 	;    ;eax = file descriptor/number
  3644                              <1> 	;     ebx = file descriptor/number ; 18/08/2020 	
  3645                              <1> 	; OUTPUT:
  3646                              <1> 	;     bl = open mode & status flag ; 27/03/2020
  3647                              <1> 	;        (bit 0 open mode flag, 0 = read, 1 = write)  
  3648                              <1> 	;    eax = inode number (in AX)
  3649                              <1> 	;          If eax = 0 -> file not open
  3650                              <1> 	;   byte [cdev] = logical drive number (of inode in eax)
  3651                              <1> 	;	
  3652                              <1> 	; Modified registers: eax, ebx
  3653                              <1> 
  3654                              <1> 	; 16/05/2021 ('getf' procedure, unix v7 x86 'fio.c')
  3655                              <1> 	; /*
  3656                              <1> 	;  * Convert a user supplied
  3657                              <1> 	;  * file descriptor into a pointer
  3658                              <1> 	;  * to a file structure.
  3659                              <1> 	;  * Only task is to check range
  3660                              <1> 	;  * of the descriptor.
  3661                              <1> 	;  */
  3662                              <1> 	; struct file *
  3663                              <1> 	; getf(f)
  3664                              <1> 	;
  3665                              <1> 	; 18/08/2020
  3666                              <1> 	; 	ebx = file descriptor/number
  3667                              <1> 
  3668                              <1> 	; 16/05/2021
  3669                              <1> 	;NOFILE	equ 10 ; 08/01/2022
  3670                              <1> 
  3671                              <1> 	; 18/08/2020
  3672                              <1> 	;mov	ebx, eax
  3673                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3674                              <1> 
  3675                              <1> 	; ebx = file descriptor/number
  3676                              <1> 
  3677                              <1> 	; 18/08/2020
  3678 00004939 29C0                <1> 	sub	eax, eax ; eax = 0
  3679                              <1>  
  3680 0000493B 83FB0A              <1> 	cmp	ebx, 10 ; cmp ebx, NOFILE ; 16/05/2021
  3681                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3682 0000493E 732E                <1>         jnb	short getf2 ; 13/05/2015
  3683                              <1> 	;jnb	error
  3684                              <1> 		; bhis error3 / u.fp is table of users open files,
  3685                              <1> 			    ; / index in fsp table
  3686                              <1> 	; 08/01/2022
  3687 00004940 8A83[B2740000]      <1> 	mov	al, [ebx+u.fp]
  3688                              <1> 	;mov	bl, [ebx+u.fp]
  3689                              <1> 		; movb u.fp(r1),r1 / r1 contains number of entry 
  3690                              <1> 		                 ; / in fsp table
  3691 00004946 08C0                <1> 	or	al, al ; 08/01/2022
  3692                              <1> 	;or	bl, bl
  3693                              <1> 	;jnz	short getf3
  3694 00004948 7424                <1> 	jz	short getf2 ; 18/08/2020
  3695                              <1> 	;;jz	short getf4
  3696                              <1> 		; beq 1f / if its zero return
  3697                              <1> ;getf2:
  3698                              <1> ;	; 'File not open !' error (ax=0)
  3699                              <1> ;	;sub	eax, eax ; 18/08/2020
  3700                              <1> ;	retn
  3701                              <1> ;getf3:	
  3702                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3703                              <1> 	;
  3704                              <1> 	; 'fsp' table (10 bytes/entry)
  3705                              <1> 	; bit 15				   bit 0
  3706                              <1> 	; ---|-------------------------------------------
  3707                              <1> 	; r/w|		i-number of open file
  3708                              <1> 	; ---|-------------------------------------------
  3709                              <1> 	;		   device number
  3710                              <1> 	; -----------------------------------------------
  3711                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3712                              <1> 	; -----------------------------------------------
  3713                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3714                              <1> 	; ----------------------|------------------------
  3715                              <1> 	;  flag that says file 	| number of processes
  3716                              <1> 	;   has been deleted	| that have file open 
  3717                              <1> 	; ----------------------|------------------------
  3718                              <1> 
  3719                              <1> 	; Retro UNIX 386 v2 modification ! (27/03/2020)
  3720                              <1> 
  3721                              <1> 	; bit 15 				    bit 0
  3722                              <1> 	; ----------------------------------------------- byte 0
  3723                              <1> 	;    	       i-number of open file           
  3724                              <1> 	; ----------------------------------------------- byte 2
  3725                              <1> 	;          high word of 32 bit i-number       
  3726                              <1> 	; ----------------------------------------------- byte 4
  3727                              <1> 	;    open mode & status  |   device number     
  3728                              <1> 	; ----------------------------------------------- byte 6
  3729                              <1> 	;       reserved byte    |    open count  
  3730                              <1> 	; ----------------------------------------------- byte 8
  3731                              <1> 	;   offset pointer, i.e., r/w pointer to file 
  3732                              <1> 	; ----------------------------------------------- byte 10
  3733                              <1> 	;     64 bit file offset pointer (bit 16-31)  
  3734                              <1> 	; ----------------------------------------------- byte 12
  3735                              <1> 	;     64 bit file offset pointer (bit 32-47)   
  3736                              <1> 	; ----------------------------------------------- byte 14
  3737                              <1> 	;     64 bit file offset pointer (bit 48-63)  
  3738                              <1> 	; ----------------------------------------------- byte 16
  3739                              <1> 	
  3740                              <1> 	; 11/05/2015 - Retro UNIX 386 v1
  3741                              <1> 	;mov	eax, 10
  3742                              <1> 
  3743                              <1> 	; 27/03/2020 - Retro UNIX 386 v2	
  3744                              <1> 	;mov	eax, opfls.size ; mov eax, 16
  3745                              <1> 	
  3746                              <1> 	;sub	eax, eax ; 18/08/2020 ; eax = 0
  3747                              <1> 
  3748                              <1> 	;mov	al, opfls.size  ; mov al, 16
  3749                              <1> 	;
  3750                              <1> 	;mul	bl
  3751                              <1> 	;;mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3752                              <1> 	;; 27/03/2020
  3753                              <1> 	;mov	ebx, fsp-(opfls.size-opfls.offset) ; fsp-8
  3754                              <1> 	
  3755                              <1> 	;add	ebx, eax
  3756                              <1> 		; asl r1
  3757                              <1> 		; asl r1 / multiply by 8 to get index into 
  3758                              <1> 		       ; / fsp table entry
  3759                              <1> 		; asl r1
  3760                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3761                              <1> 			      ; / in the fsp entry
  3762                              <1> 	; 08/01/2022
  3763 0000494A 88C3                <1> 	mov	bl, al
  3764                              <1> 	; 18/08/2020
  3765 0000494C FECB                <1> 	dec	bl ; zero based fsp table entry number
  3766                              <1> 	;shl	bl, 4 ; * 16 ; opfls.size
  3767                              <1> 	; 08/01/2022
  3768 0000494E C1E304              <1> 	shl	ebx, 4 ; * 16 ; opfls.size
  3769 00004951 81C3[4C710000]      <1> 	add	ebx, fsp+8 ; opfls.offset	
  3770                              <1> 	; ebx = address of the file offset pointer 
  3771                              <1> 	;	(not file offset! not fsp entry address !)
  3772                              <1> 
  3773 00004957 891D[BC740000]      <1> 	mov	[u.fofp], ebx
  3774                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3775                              <1> 			     ; / in fsp entry in u.fofp
  3776                              <1> 	; 18/08/2020
  3777 0000495D 8A43FD              <1> 	mov	al, [ebx-3]  ; open mode & status flags
  3778                              <1> 
  3779 00004960 50                  <1> 	push	eax
  3780                              <1> 
  3781                              <1> 	;mov	ax, [ebx]
  3782                              <1> 	;;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3783                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3784                              <1> 			     ;;dev number is in 1 byte
  3785                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3786                              <1> 
  3787                              <1> 	; 18/08/2020
  3788 00004961 8A43FC              <1> 	mov	al, [ebx-4]  ; logical drive number
  3789                              <1> 
  3790 00004964 A2[89740000]        <1> 	mov	[cdev], al
  3791                              <1> 
  3792                              <1> 	;dec	ebx
  3793                              <1> 	;dec	ebx
  3794                              <1> 	; 18/08/2020
  3795 00004969 668B43F8            <1> 	mov	ax, [ebx-8]
  3796                              <1> 		; mov -(r1),r1 / and the i-number r1
  3797                              <1> 
  3798 0000496D 5B                  <1> 	pop	ebx ; ebx = bl = open mode and status flag
  3799                              <1> 		; (bit 0 is open mode flag, 0 = read, 1 = write)
  3800                              <1> 	; eax = inode number (in ax)	
  3801                              <1> 
  3802                              <1> getf2:	; 18/08/2020
  3803                              <1> getf4:	; 1: ; 08/01/2022
  3804 0000496E C3                  <1> 	retn
  3805                              <1> 		; rts r0
  3806                              <1> 
  3807                              <1> 	; 08/01/2022
  3808                              <1> 	; 19/12/2021
  3809                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3810                              <1> namei:
  3811                              <1> 	; 18/10/2021
  3812                              <1> 	; 12/06/2021
  3813                              <1> 	; 01/05/2021
  3814                              <1> 	; 26/03/2021
  3815                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  3816                              <1> 	; 04/12/2015 (14 byte file names)
  3817                              <1> 	; 18/10/2015 (nbase, ncount)
  3818                              <1> 	; 12/10/2015
  3819                              <1> 	; 21/08/2015
  3820                              <1> 	; 18/07/2015
  3821                              <1> 	; 02/07/2015
  3822                              <1> 	; 17/06/2015
  3823                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3824                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3825                              <1> 	;
  3826                              <1> 	; 'namei' takes a file path name and returns i-number of
  3827                              <1> 	; the file in the current directory or the root directory
  3828                              <1> 	; (if the first character of the pathname is '/').	
  3829                              <1> 	;
  3830                              <1> 	; INPUTS ->
  3831                              <1> 	;    u.namep - points to a file path name
  3832                              <1> 	;    u.cdir - i-number of users directory
  3833                              <1> 	;    u.cdev - device number on which user directory resides	
  3834                              <1> 	; OUTPUTS ->
  3835                              <1> 	;    r1 - i-number of file
  3836                              <1> 	;    cdev
  3837                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3838                              <1> 	;               occurs in the search for file path name.
  3839                              <1> 	;	        If no match u.dirb points to the end of 
  3840                              <1> 	;               the directory and r1 = i-number of the current
  3841                              <1> 	;	        directory.	
  3842                              <1> 	; ((AX = R1))
  3843                              <1> 	;
  3844                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3845                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3846                              <1> 	;
  3847                              <1> 
  3848                              <1> 	;mov	ax, [u.cdir]
  3849                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3850                              <1> 			      ; / in r1
  3851                              <1> 	; 01/05/2021
  3852 0000496F A1[AC740000]        <1> 	mov	eax, [u.cdir]	
  3853 00004974 8A15[B0740000]      <1> 	mov	dl, [u.cdrv]
  3854 0000497A 8815[89740000]      <1> 	mov	[cdev], dl
  3855                              <1> 	;mov	dx, [u.cdrv]
  3856                              <1> 	;mov	[cdev], dx	; NOTE: Retro UNIX 8086 v1 
  3857                              <1> 				; device/drive number is in 1 byte, 
  3858                              <1> 				; not in 1 word!
  3859                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3860                              <1> 				; / into cdev
  3861                              <1> 	; 12/10/2015
  3862                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3863                              <1>       	; convert virtual (pathname) addr to physical address
  3864 00004980 E808010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3865                              <1> 		; esi = physical address of [u.namep]
  3866                              <1> 		; ecx = byte count in the page
  3867 00004985 803E2F              <1> 	cmp	byte [esi], '/'
  3868                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3869 00004988 751C                <1> 	jne	short namei_1
  3870                              <1> 		; bne 1f
  3871 0000498A FF05[C4740000]      <1> 	inc	dword [u.namep]
  3872                              <1> 		; inc u.namep / go to next char
  3873                              <1> 	;dec	cx ; remain byte count in the page
  3874 00004990 49                  <1> 	dec	ecx ; 18/10/2021
  3875 00004991 7506                <1> 	jnz	short namei_0
  3876                              <1> 	; 12/10/2015
  3877 00004993 E8F5000000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3878                              <1> 		; esi = physical address (page start + offset)
  3879                              <1> 		; ecx = byte count in the page
  3880 00004998 4E                  <1> 	dec	esi
  3881                              <1> namei_0:
  3882 00004999 46                  <1> 	inc 	esi  ; go to next char
  3883                              <1> 	;mov	ax, [rootdir] ; 09/07/2013
  3884                              <1> 	; 18/10/2021
  3885 0000499A A1[90740000]        <1> 	mov	eax, [rootdir]
  3886                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3887 0000499F C605[89740000]00    <1> 	mov	byte [cdev], 0
  3888                              <1> 		; clr cdev / clear device number
  3889                              <1> namei_1: ; 1:
  3890 000049A6 F606FF              <1> 	test	byte [esi], 0FFh
  3891                              <1> 	;jz	short getf4
  3892                              <1> 	; 26/03/2021
  3893                              <1> 	;jz	short getf2 ; retn
  3894                              <1> 	;;jz	nig
  3895                              <1> 		; tstb *u.namep / is the character in file name a nul
  3896                              <1> 		; beq nig / yes, end of file name reached; 
  3897                              <1> 			; / branch to "nig"
  3898                              <1> 	; 19/12/2021
  3899                              <1> namei_9:
  3900                              <1> 	; 12/06/2021
  3901                              <1> 	;jnz	short namei_2
  3902                              <1> 	;retn
  3903                              <1> 	; 08/01/2022
  3904 000049A9 74C3                <1> 	jz	short getf4
  3905                              <1> namei_2: ; 1:
  3906                              <1> 	; 18/10/2015
  3907 000049AB 8935[2C750000]      <1> 	mov 	[nbase], esi
  3908                              <1> 	;mov 	[ncount], cx
  3909                              <1> 	; 18/10/2021
  3910 000049B1 890D[30750000]      <1> 	mov	[ncount], ecx
  3911                              <1> 	;
  3912                              <1> 	;;mov	dx, 2
  3913                              <1> 	;mov	dl, 2 ; user flag (read, non-owner)
  3914                              <1> 	; 25/03/2021
  3915                              <1> 	;mov	dx, 100h ; IREAD - read, owner 
  3916                              <1> 	; 18/10/2021
  3917 000049B7 29D2                <1> 	sub	edx, edx
  3918 000049B9 FEC6                <1> 	inc	dh ; dx = 100h ; IREAD - read, owner 
  3919 000049BB E82E0B0000          <1> 	call	access
  3920                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3921                              <1> 	; 'access' will not return here if user has not "r" permission !
  3922                              <1> 
  3923                              <1> 	;test 	word [i.flgs], 4000h
  3924                              <1> 	;	; bit $40000,i.flgs / directory i-node?
  3925                              <1>         ;jz	short namei_err
  3926                              <1> 		; beq error3 / no, got an error
  3927                              <1> 	; 26/03/2021 
  3928                              <1> ;	mov	al, [i.flgs+1]
  3929                              <1> ;	;test	al, 80h ; IFREG ; 80h
  3930                              <1> ;	;jz	short namei_err ; not a regular file ! (device!?)
  3931                              <1> ;	;and	al, 40h ; IFDIR ; 40h
  3932                              <1> ;	;jz	short namei_err ; not a sub directory !
  3933                              <1> ;	shl	al, 1 ; 80h (IFREG flag) -> cf = 1
  3934                              <1> ;	jnc	short namei_err ; not a regular file ! (device!?)
  3935                              <1> ;	shl	al, 1 ; 80h (IFDIR flag) -> cf = 1
  3936                              <1> ;	jnc	short namei_err ; not a sub directory !
  3937                              <1> 
  3938                              <1> 	; 27/03/2021
  3939 000049C0 E8F9000000          <1> 	call	chk_dir ; check for directory, jump to 'error' if not
  3940                              <1> 	; CPU will be here if the inode is a (valid) directory inode
  3941                              <1> 
  3942                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3943                              <1> 	;xor	eax, eax
  3944                              <1> 	;mov	[u.off], eax ; 0
  3945                              <1> 	; 01/05/2021 - Retro UNIX 386 v2 inode structure
  3946 000049C5 A1[4C700000]        <1> 	mov	eax, [i.size]
  3947                              <1> 	;mov	ax, [i.size]
  3948 000049CA A3[C0740000]        <1> 	mov	[u.dirp], eax
  3949                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3950                              <1> 		; clr u.off / u.off is file offset used by user
  3951                              <1> 	; 18/10/2021
  3952 000049CF 31C0                <1> 	xor	eax, eax
  3953                              <1> 	;mov	[u.off], eax ; 0
  3954 000049D1 BB[C8740000]        <1> 	mov	ebx, u.off
  3955 000049D6 8903                <1> 	mov	[ebx], eax ; mov dword [u.off], 0
  3956                              <1> 	;
  3957 000049D8 891D[BC740000]      <1> 	mov	[u.fofp], ebx ; u.off ; 18/10/2021
  3958                              <1> 	;mov	dword [u.fofp], u.off
  3959                              <1> 			; mov $u.off,u.fofp / u.fofp is a pointer to 
  3960                              <1> 				  ; / the offset portion of fsp entry
  3961                              <1> namei_3: ; 2:
  3962 000049DE C705[CC740000]-     <1> 	mov	dword [u.base], u.dirbuf
  3962 000049E4 [E0740000]          <1>
  3963                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3964                              <1> 				    ; / copied from a directory
  3965 000049E8 C705[D0740000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3965 000049F0 0000                <1>
  3966                              <1>  		; mov $10.,u.count / u.count is byte count 
  3967                              <1> 				 ; / for reads and writes
  3968                              <1> 	;mov 	ax, [ii]
  3969                              <1> 	; 18/10/2021
  3970 000049F2 A1[84740000]        <1> 	mov	eax, [ii] ; (32 bit inode number)
  3971                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3972 000049F7 FE05[1A750000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3973 000049FD E87C0D0000          <1>     	call	readi
  3974                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3975                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3976                              <1> 
  3977 00004A02 8B0D[D4740000]      <1> 	mov 	ecx, [u.nread]
  3978 00004A08 09C9                <1> 	or 	ecx, ecx
  3979                              <1> 		; tst u.nread
  3980 00004A0A 741A                <1> 	jz	short nib
  3981                              <1> 		; ble nib / gives error return
  3982                              <1> 	;
  3983                              <1> 	;mov 	bx, [u.dirbuf]
  3984                              <1> 	;and 	bx, bx       
  3985                              <1> 	; 18/10/2021
  3986 00004A0C 66F705[E0740000]FF- <1> 	test	word [u.dirbuf], 0FFFFh
  3986 00004A14 FF                  <1>
  3987                              <1> 		; tst u.dirbuf /
  3988 00004A15 7513                <1> 	jnz	short namei_4
  3989                              <1> 		; bne 3f / branch when active directory entry 
  3990                              <1> 		       ; / (i-node word in entry non zero)
  3991 00004A17 A1[C8740000]        <1> 	mov	eax, [u.off]
  3992 00004A1C 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3993 00004A1F A3[C0740000]        <1> 	mov	[u.dirp], eax
  3994                              <1> 		; mov u.off,u.dirp
  3995                              <1> 		; sub $10.,u.dirp
  3996 00004A24 EBB8                <1> 	jmp	short namei_3
  3997                              <1> 		; br 2b
  3998                              <1> 
  3999                              <1> 	; 18/07/2013
  4000                              <1> nib: 
  4001 00004A26 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  4002 00004A28 F9                  <1> 	stc
  4003                              <1> nig:
  4004 00004A29 C3                  <1> 	retn
  4005                              <1> 
  4006                              <1> 	; 27/03/2021
  4007                              <1> ;namei_err:
  4008                              <1> 	; 16/06/2015
  4009                              <1> ;	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  4010                              <1> ;	jmp	error
  4011                              <1> 
  4012                              <1> namei_4: ; 3:
  4013                              <1> 	; 18/10/2015
  4014                              <1> 	; 12/10/2015
  4015                              <1> 	; 21/08/2015
  4016                              <1> 	; 18/07/2015
  4017 00004A2A 8B2D[C4740000]      <1> 	mov	ebp, [u.namep]
  4018                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  4019 00004A30 BF[E2740000]        <1> 	mov 	edi, u.dirbuf + 2
  4020                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  4021                              <1> 	; 18/10/2015
  4022 00004A35 8B35[2C750000]      <1> 	mov	esi, [nbase]
  4023                              <1> 	;mov	cx, [ncount]
  4024                              <1> 	;and	cx, cx
  4025                              <1> 	; 18/10/2021
  4026 00004A3B 8B0D[30750000]      <1> 	mov	ecx, [ncount]
  4027 00004A41 21C9                <1> 	and	ecx, ecx
  4028 00004A43 7505                <1> 	jnz	short namei_5	
  4029                              <1> 	;
  4030 00004A45 E849000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4031                              <1> 		; esi = physical address (page start + offset)
  4032                              <1> 		; ecx = byte count in the page
  4033                              <1> namei_5: ; 3:
  4034 00004A4A 45                  <1> 	inc	ebp ; 18/07/2015
  4035 00004A4B AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  4036                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  4037 00004A4C 08C0                <1> 	or 	al, al
  4038 00004A4E 741C                <1> 	jz 	short namei_7
  4039                              <1> 		; beq 3f / if char is nul, then the last char in string
  4040                              <1> 			; / has been moved
  4041 00004A50 3C2F                <1> 	cmp	al, '/'
  4042                              <1> 		; cmp r4,$'/ / is char a </>
  4043 00004A52 7418                <1> 	je 	short namei_7
  4044                              <1> 		; beq 3f	
  4045                              <1> 	; 12/10/2015
  4046                              <1> 	;dec	cx ; remain byte count in the page
  4047 00004A54 49                  <1> 	dec	ecx ; 18/10/2021
  4048 00004A55 7505                <1> 	jnz	short namei_6
  4049 00004A57 E837000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4050                              <1> 		; esi = physical address (page start + offset)
  4051                              <1> 		; ecx = byte count in the page
  4052                              <1> namei_6:
  4053 00004A5C 81FF[F0740000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4054                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  4055                              <1> 				     ; / all 8 bytes of file name
  4056 00004A62 74E6                <1> 	je	short namei_5
  4057                              <1> 		; beq 3b
  4058 00004A64 AE                  <1> 	scasb	
  4059                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  4060                              <1> 			      ; / char read from directory
  4061 00004A65 74E3                <1> 	je 	short namei_5
  4062                              <1> 		; beq 3b / branch if chars match
  4063                              <1> namei_10:
  4064 00004A67 E972FFFFFF          <1>         jmp	namei_3 ; 2b
  4065                              <1> 		; br 2b / file names do not match go to next directory entry
  4066                              <1> namei_7: ; 3:
  4067 00004A6C 81FF[F0740000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4068                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  4069 00004A72 7405                <1> 	je	short namei_8
  4070                              <1> 		; beq 3f
  4071                              <1> 	;mov 	ah, [edi]
  4072                              <1> 	;;inc 	edi 
  4073                              <1> 	;and 	ah, ah
  4074                              <1> 	;	; tstb (r3)+ /
  4075                              <1>         ; 18/10/2021
  4076 00004A74 F607FF              <1> 	test	byte [edi], 0FFh
  4077                              <1> 	; 08/01/2021
  4078 00004A77 75EE                <1> 	jnz	short namei_10 
  4079                              <1> 	;jnz	namei_3
  4080                              <1> 		; bne 2b
  4081                              <1> namei_8: ; 3
  4082 00004A79 892D[C4740000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  4083                              <1> 		; mov r2,u.namep / u.namep points to char 
  4084                              <1> 			       ; / following a / or nul
  4085                              <1> 	;mov	bx, [u.dirbuf]
  4086                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  4087                              <1> 				; / entry to r1
  4088 00004A7F 20C0                <1> 	and 	al, al
  4089                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  4090                              <1> 		      ;  / if r4 = </> then go to next directory
  4091                              <1> 	;mov	ax, bx
  4092                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  4093                              <1>         ; 18/10/2021 (16 bit inode number in 32 bit register)
  4094 00004A81 0FB705[E0740000]    <1> 	movzx	eax, word [u.dirbuf] 
  4095                              <1> 	; 19/12/2021
  4096 00004A88 E91CFFFFFF          <1> 	jmp	namei_9 ; eax = inode number
  4097                              <1> ;	jnz	namei_2 
  4098                              <1> ;		; bne 1b
  4099                              <1> ;	; AX = i-number of the file
  4100                              <1> ;;;nig:
  4101                              <1> ;	retn
  4102                              <1> 		; tst (r0)+ / gives non-error return
  4103                              <1> ;;nib:
  4104                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  4105                              <1> 		       ; ax = 0 -> file not found 
  4106                              <1> ;;	stc	; 27/05/2013
  4107                              <1> ;;	retn
  4108                              <1> 		; rts r0
  4109                              <1> 
  4110                              <1> trans_addr_nmbp:
  4111                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4112                              <1> 	; 18/10/2015
  4113                              <1> 	; 12/10/2015
  4114 00004A8D 8B2D[C4740000]      <1> 	mov 	ebp, [u.namep]
  4115                              <1> trans_addr_nm: 
  4116                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4117                              <1> 	; Convert virtual (pathname) address to physical address
  4118                              <1> 	; (Retro UNIX 386 v1 feature only !)
  4119                              <1> 	; 18/10/2015
  4120                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  4121                              <1> 	; 02/07/2015
  4122                              <1> 	; 17/06/2015
  4123                              <1> 	; 16/06/2015
  4124                              <1> 	;
  4125                              <1> 	; INPUTS: 
  4126                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  4127                              <1> 	;	[u.pgdir] = user's page directory
  4128                              <1> 	; OUTPUT:
  4129                              <1> 	;       esi = physical address of the pathname
  4130                              <1> 	;	ecx = remain byte count in the page
  4131                              <1> 	;
  4132                              <1> 	; (Modified registers: EBX, ECX, EDX, ESI) ; 18/10/2021
  4133                              <1> 	;
  4134                              <1> 
  4135                              <1> 	; 18/10/2021
  4136 00004A93 29C9                <1> 	sub	ecx, ecx
  4137                              <1> 	;
  4138                              <1>         ;cmp	dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  4139 00004A95 390D[0C750000]      <1> 	cmp	[u.ppgdir], ecx ; 0 ; 18/10/2021
  4140 00004A9B 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  4141                              <1> 				     ; it is already physical address
  4142 00004A9D 50                  <1>    	push	eax	
  4143 00004A9E 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  4144 00004AA0 E8EDE6FFFF          <1>        	call	get_physical_addr ; get physical address
  4145 00004AA5 7204                <1> 	jc	short tr_addr_nm_err
  4146                              <1> 	; 18/10/2015
  4147                              <1> 	; eax = physical address 
  4148                              <1> 	; ecx = remain byte count in page (1-4096) ; 18/10/2021
  4149                              <1> 		; 12/10/2015 (cx = [u.pncount])
  4150 00004AA7 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  4151 00004AA9 58                  <1> 	pop	eax 
  4152 00004AAA C3                  <1> 	retn
  4153                              <1> 
  4154                              <1> tr_addr_nm_err:
  4155 00004AAB A3[1C750000]        <1> 	mov	[u.error], eax
  4156                              <1> 	;pop 	eax
  4157 00004AB0 E919F0FFFF          <1> 	jmp	error
  4158                              <1> 
  4159                              <1> trans_addr_nmk:
  4160                              <1> 	; 12/10/2015
  4161                              <1> 	; 02/07/2015
  4162 00004AB5 8B35[C4740000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  4163                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  4164                              <1> 	; 18/10/2021
  4165 00004ABB B510                <1> 	mov	ch, PAGE_SIZE/256
  4166 00004ABD C3                  <1> 	retn
  4167                              <1> 
  4168                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  4169                              <1> chk_dir:
  4170                              <1> 	; 12/06/2021
  4171                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  4172                              <1> 	; Check for directory inode
  4173                              <1> 
  4174 00004ABE 8A0D[45700000]      <1> 	mov	cl, [i.flgs+1]
  4175                              <1> 	;test	cl, 80h ; IFREG ; 80h
  4176                              <1> 	;jz	short chk_dir_err ; not a regular file ! (device!?)
  4177                              <1> 	;and	cl, 40h ; IFDIR ; 40h
  4178                              <1> 	;jz	short chk_dir_err ; not a sub directory !
  4179 00004AC4 D0E1                <1> 	shl	cl, 1 ; 80h (IFREG flag) -> cf = 1
  4180 00004AC6 7305                <1> 	jnc	short chk_dir_err ; not a regular file ! (device!?)
  4181 00004AC8 D0E1                <1> 	shl	cl, 1 ; 40h (IFDIR flag) -> cf = 1
  4182 00004ACA 7301                <1> 	jnc	short chk_dir_err ; not a sub directory !
  4183                              <1> 	; 12/06/2021
  4184 00004ACC C3                  <1> 	retn
  4185                              <1> chk_dir_err:
  4186 00004ACD C705[1C750000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4186 00004AD5 0000                <1>
  4187 00004AD7 E9F2EFFFFF          <1> 	jmp	error
  4188                              <1> 
  4189                              <1> 	; 06/02/2022
  4190                              <1> 	; 08/01/2022
  4191                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  4192                              <1> syschdir:
  4193                              <1> 	; / makes the directory specified in the argument
  4194                              <1> 	; / the current directory
  4195                              <1> 	;
  4196                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  4197                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4198                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  4199                              <1> 	;
  4200                              <1> 	; 'syschdir' makes the directory specified in its argument
  4201                              <1> 	; the current working directory.
  4202                              <1> 	;
  4203                              <1> 	; Calling sequence:
  4204                              <1> 	;	syschdir; name
  4205                              <1> 	; Arguments:
  4206                              <1> 	;	name - address of the path name of a directory
  4207                              <1> 	;	       terminated by nul byte.	
  4208                              <1> 	; Inputs: -
  4209                              <1> 	; Outputs: -
  4210                              <1> 	; ...............................................................
  4211                              <1> 	;				
  4212                              <1> 	; Retro UNIX 8086 v1 modification:
  4213                              <1> 	;	 The user/application program puts address of 
  4214                              <1> 	;	 the path name in BX register as 'syschdir' 
  4215                              <1> 	; 	 system call argument.
  4216                              <1> 
  4217 00004ADC 891D[C4740000]      <1> 	mov	[u.namep], ebx
  4218                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  4219 00004AE2 E888FEFFFF          <1> 	call	namei
  4220                              <1> 		; jsr r0,namei / find its i-number
  4221                              <1> 	;jc	error
  4222                              <1> 		; br error3
  4223 00004AE7 730F                <1> 	jnc	short syschdir0
  4224                              <1> 	; 'directory not found !' error
  4225 00004AE9 C705[1C750000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  4225 00004AF1 0000                <1>
  4226 00004AF3 E9D6EFFFFF          <1> 	jmp	error
  4227                              <1> syschdir0:
  4228                              <1> 	; 08/01/2022
  4229 00004AF8 66BA0001            <1> 	mov	dx, 100h  ; read access ; IREAD (100h)
  4230 00004AFC E8ED090000          <1> 	call	access
  4231                              <1> 		; jsr r0,access; 2 / get i-node into core
  4232                              <1> 	
  4233                              <1> 	; 06/02/2022
  4234                              <1> 	;; 01/01/2022 (runix v2 fs inode flag)
  4235                              <1> 	;test	byte [i.flgs+1], 80h ; regular file ?
  4236                              <1> 	;jz	short syschdir2 ; no, error!
  4237                              <1> 	;test	byte [i.flgs+1], 40h ; directory flag ?
  4238                              <1> 	;;test	word [i.flgs], 4000h
  4239                              <1> 	;	; bit $40000,i.flgs / is it a directory?
  4240                              <1> 	;;jz	error 
  4241                              <1> 	;	; beq error3 / no error
  4242                              <1> 	;jnz	short syschdir1
  4243                              <1> ;syschdir2:
  4244                              <1> 	;mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4245                              <1> 	;jmp	error
  4246                              <1> 
  4247                              <1> 	; 06/02/2022
  4248                              <1> 	; check for directory, jump to 'error' if not
  4249 00004B01 E8B8FFFFFF          <1> 	call	chk_dir
  4250                              <1> 	; (cpu will not return here
  4251                              <1> 	;  if the inode it is not a valid dir inode)
  4252                              <1> 
  4253                              <1> syschdir1:
  4254 00004B06 66A3[AC740000]      <1> 	mov	[u.cdir], ax
  4255                              <1> 		; mov r1,u.cdir / move i-number to users 
  4256                              <1> 			      ; / current directory
  4257                              <1> 	;mov	ax, [cdev]
  4258                              <1> 	;mov	[u.cdrv], ax
  4259                              <1> 	; 08/01/2022
  4260 00004B0C A0[89740000]        <1> 	mov	al, [cdev]
  4261 00004B11 A2[B0740000]        <1> 	mov	[u.cdrv], al
  4262                              <1> 		; mov cdev,u.cdev / move its device to users 
  4263                              <1> 			        ; / current device
  4264 00004B16 E9D3EFFFFF          <1> 	jmp	sysret
  4265                              <1> 		; br sysret3
  4266                              <1> 
  4267                              <1> syschmod: ; < change mode of file >
  4268                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4269                              <1> 	; 01/05/2021
  4270                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4271                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4272                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4273                              <1> 	;
  4274                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4275                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4276                              <1> 	; changed to 'mode'.
  4277                              <1> 	;
  4278                              <1> 	; Calling sequence:
  4279                              <1> 	;	syschmod; name; mode
  4280                              <1> 	; Arguments:
  4281                              <1> 	;	name - address of the file name
  4282                              <1> 	;	       terminated by null byte.
  4283                              <1> 	;	mode - (new) mode/flags < attributes >
  4284                              <1> 	;	
  4285                              <1> 	; Inputs: -
  4286                              <1> 	; Outputs: -
  4287                              <1> 	; ...............................................................
  4288                              <1> 	;				
  4289                              <1> 	; Retro UNIX 8086 v1 modification: 
  4290                              <1> 	;       'syschmod' system call has two arguments; so,
  4291                              <1> 	;	* 1st argument, name is pointed to by BX register
  4292                              <1> 	;	* 2nd argument, mode is in CX register
  4293                              <1> 	;
  4294                              <1> 	; Mode bits (Flags):
  4295                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4296                              <1> 	;	bit 14 - directory flag (4000h)
  4297                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4298                              <1> 	;	bit 12 - large file flag (1000h)
  4299                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4300                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4301                              <1> 	;	bit 4 - executable flag (10h)
  4302                              <1> 	;	bit 3 - read permission for owner (08h)
  4303                              <1> 	;	bit 2 - write permission for owner (04h)
  4304                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4305                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4306                              <1> 
  4307                              <1> 	; 01/05/2021 (07/02/2020)
  4308                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  4309                              <1> 	; 	bit 15 - IFREG - regular file (8000h)
  4310                              <1> 	;	bit 14 - IFDIR - directory (4000h)
  4311                              <1> 	;	bit 13 - IRSVD - 0 - reserved/mounted bit (2000h)
  4312                              <1> 	; 	bit 12 - ILARG - large file addressing bit (1000h)
  4313                              <1> 	; 	bit 11 - ISUID - set user id on exec (800h)
  4314                              <1> 	;	bit 10 - ISGID - set group id on exec (400h)
  4315                              <1> 	; 	bit  9 - IEXTT - 0 - use extents (200h)
  4316                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4317                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4318                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4319                              <1> 	; 	bit  5 - read, group (20h)
  4320                              <1> 	; 	bit  4 - write, group (10h)
  4321                              <1> 	; 	bit  3 - execute, group (08h)
  4322                              <1> 	;	bit  2 - read, others (04h)
  4323                              <1> 	; 	bit  1 - write, others (02h)
  4324                              <1> 	; 	bit  0 - execute, others (01h)
  4325                              <1> 	;
  4326                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  4327                              <1> 	;	bit 15 - IFREG - 0 - device file (8000h)
  4328                              <1> 	; 	bit 14 - IFBLK - block device (4000h)
  4329                              <1> 	; 	bit 13 - IFCHR - 1 - character special (2000h)
  4330                              <1> 	;	bit 12 - IFIFO - fifo special (1000h)
  4331                              <1> 	; 	bit 11 - IPIPE - pipe special (800h)
  4332                              <1> 	;	bit 10 - IREDIR - redirected (400h)
  4333                              <1> 	;	bit  9 - IEXTR - external device driver (200h)
  4334                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4335                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4336                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4337                              <1> 	; 	bit  5 - read, group (20h)
  4338                              <1> 	; 	bit  4 - write, group (10h)
  4339                              <1> 	; 	bit  3 - execute, group (08h)
  4340                              <1> 	;	bit  2 - read, others (04h)
  4341                              <1> 	; 	bit  1 - write, others (02h)
  4342                              <1> 	; 	bit  0 - execute, others (01h)
  4343                              <1> 
  4344                              <1> 	; / name; mode
  4345 00004B1B E87C000000          <1> 	call	isown
  4346                              <1> 		; jsr r0,isown / get the i-node and check user status
  4347                              <1> 
  4348                              <1> 	; 25/05/2020
  4349                              <1> 	; AL = new mode (return form 'isown', ecx -> eax)
  4350                              <1> 
  4351                              <1> 	;test	word [i.flgs], 4000h
  4352                              <1> 	;	; bit $40000,i.flgs / directory?
  4353                              <1> 	;jz	short syschmod1
  4354                              <1> 	;	; beq 2f / no
  4355                              <1> 	;; AL = (new) mode
  4356                              <1> 	;and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4357                              <1> 	;	; bic $60,r2 / su & ex / yes, clear set user id and 
  4358                              <1> 	;		   ; / executable modes
  4359                              <1> 
  4360                              <1> 	; 01/05/2021
  4361                              <1> 	; AX = new mode (9 bits for devices or 12 bits files)
  4362 00004B20 8A15[45700000]      <1> 	mov	dl, [i.flgs+1]
  4363                              <1> 	; 09/01/2022
  4364 00004B26 F6C280              <1> 	test	dl, 80h ; regular file
  4365 00004B29 7416                <1> 	jz	short syschmod1 ; device file
  4366 00004B2B F6C240              <1> 	test	dl, 40h ; directory
  4367 00004B2E 7511                <1> 	jnz	short syschmod1
  4368                              <1> 	; regular file
  4369 00004B30 6625FF0D            <1> 	and	ax, 0DFFh ; clear bit 9, 12-15 (of new mode)
  4370                              <1> 	; clear bit 8,10,11 of current mode/flags
  4371 00004B34 80E2F2              <1> 	and	dl, 0F2h ; and dl, 11110010b
  4372                              <1> syschmod0:
  4373 00004B37 08D4                <1> 	or	ah, dl
  4374 00004B39 66A3[44700000]      <1> 	mov	[i.flgs], ax	
  4375 00004B3F EB4A                <1> 	jmp	short syschmod2
  4376                              <1> syschmod1: 
  4377                              <1> 	; device or directory	
  4378 00004B41 6625B601            <1> 	and	ax, 1B6h ; clear bit 9-15 & bit 0,3,6 (EXEC bits)
  4379                              <1> 	; clear bit 8 (IREAD) of current mode/flags
  4380                              <1> 	;	 (dl contains flag bits 8-15)
  4381 00004B45 80E2FE              <1> 	and	dl, ~1 ; and dl, 11111110b 
  4382 00004B48 EBED                <1> 	jmp	short syschmod0
  4383                              <1> 
  4384                              <1> ;syschmod1: ; 2:
  4385                              <1> 	;mov	[i.flgs], al	
  4386                              <1> 	;	; movb r2,i.flgs / move remaining mode to i.flgs
  4387                              <1> 
  4388                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4389                              <1> 	;mov	byte [imodx], 1 ; (flag means file data is same
  4390                              <1> 	;			;  but inode's itself has been modified)
  4391                              <1> 	;call	setimod
  4392                              <1> 	;jmp	sysret
  4393                              <1> 
  4394                              <1> 	; 25/05/2020
  4395                              <1> 	;jmp	short syschmod2
  4396                              <1> 
  4397                              <1> syschown: ; < change owner of file >
  4398                              <1> 	; 14/02/2022
  4399                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4400                              <1> 	; 01/05/2021
  4401                              <1> 	;	(change owner and group ID of file)
  4402                              <1> 	; 02/04/2021
  4403                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4404                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4405                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4406                              <1> 	;
  4407                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4408                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4409                              <1> 	; changed to 'owner'
  4410                              <1> 	;
  4411                              <1> 	; Calling sequence:
  4412                              <1> 	;	syschown; name; owner
  4413                              <1> 	; Arguments:
  4414                              <1> 	;	name - address of the file name
  4415                              <1> 	;	       terminated by null byte.
  4416                              <1> 	;	owner - (new) owner (number/ID)
  4417                              <1> 	;	
  4418                              <1> 	; Inputs: -
  4419                              <1> 	; Outputs: -
  4420                              <1> 	; ...............................................................
  4421                              <1> 	;				
  4422                              <1> 	; Retro UNIX 8086 v1 modification: 
  4423                              <1> 	;       'syschown' system call has two arguments; so,
  4424                              <1> 	;	* 1st argument, name is pointed to by BX register
  4425                              <1> 	;	* 2nd argument, owner number is in CX register
  4426                              <1> 	;
  4427                              <1> 	; / name; owner
  4428 00004B4A E84D000000          <1> 	call	isown
  4429                              <1> 		; jsr r0,isown / get the i-node and check user status
  4430                              <1> 	
  4431                              <1> 	; 25/05/2020
  4432                              <1> 	; AL = owner number (return form 'isown', ecx -> eax)
  4433                              <1> 	; 02/04/2021
  4434                              <1> 	; AX = owner number
  4435                              <1> 	; 01/05/2021
  4436                              <1> 	; byte 2 of EAX is group number
  4437                              <1> 
  4438                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013 
  4439                              <1> 	;	; tstb u.uid / super user
  4440                              <1> 	;jz	short syschown1
  4441                              <1> 	;	; beq 2f / yes, 2f
  4442 00004B4F 66833D[FA740000]00  <1> 	cmp	word [u.uid], 0
  4443 00004B57 741F                <1> 	jz	short syschown1
  4444                              <1> 
  4445                              <1> 	;test	byte [i.flgs], 20h ; 32
  4446                              <1> 	;	; bit $40,i.flgs / no, set userid on execution?
  4447                              <1> 	;;jnz	error
  4448                              <1> 	;	; bne 3f / yes error, could create Trojan Horses
  4449                              <1> 	;jz	short syschown1
  4450                              <1> 	; 01/05/2021
  4451                              <1> 	; check set user id on execution flag
  4452                              <1> 	; (protection against Trojan Horses)
  4453                              <1> 
  4454                              <1> 	; ((Note: UNIX v7 x86 'chown' source code in 'sys4.c'
  4455                              <1> 	;        does not contain this protection)) 
  4456                              <1> 
  4457                              <1> 	; 14/02/2022
  4458 00004B59 8A15[45700000]      <1> 	mov	dl, [i.flgs+1]
  4459 00004B5F F6C280              <1> 	test	dl, 80h ; IFREG ; RUNIX v2 inode flags  	
  4460 00004B62 7405                <1> 	jz	short syschown_err ; device file !
  4461                              <1> 	; 09/01/2022
  4462                              <1> 	;test	byte [i.flgs+1], 08h ; ISUID ; RUNIX v2 inode flags  	
  4463                              <1> 	; 14/02/2022
  4464 00004B64 F6C208              <1> 	test	dl, 08h	; set user id on execution
  4465 00004B67 750F                <1> 	jnz	short syschown1 ; 14/02/2022
  4466                              <1> syschown_err:
  4467                              <1> 	; 'permission denied !'
  4468 00004B69 C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4468 00004B71 0000                <1>
  4469 00004B73 E956EFFFFF          <1> 	jmp	error
  4470                              <1> syschown1: ; 2:
  4471                              <1> 	;; AL = owner (number/ID)
  4472                              <1> 	;mov	[i.uid], al ; 23/06/2015
  4473                              <1> 	;	; movb r2,i.uid / no, put the new owners id 
  4474                              <1> 	;		      ; / in the i-node
  4475                              <1> 	; 02/04/2021 (Retro UNIX 386 v2)
  4476                              <1> 	; AX = owner number
  4477 00004B78 66A3[48700000]      <1> 	mov	[i.uid], ax ; owner
  4478                              <1> 	; 14/02/2022 (Retro UNIX 386 v1.2)
  4479 00004B7E F6C204              <1> 	test	dl, 04h ; ISGID ; set grup id on execution
  4480 00004B81 7408                <1> 	jz	short syschown2
  4481                              <1> 	; 01/05/2021 (Retro UNIX 386 v2)
  4482 00004B83 C1E810              <1> 	shr	eax, 16
  4483 00004B86 A2[4A700000]        <1> 	mov	[i.gid], al ; group
  4484                              <1> syschown2:
  4485                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4486                              <1> syschmod2:
  4487                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4488 00004B8B C605[9B740000]01    <1> 	mov	byte [imodx], 1	; (flag means file data is same
  4489                              <1> 			      ;  but inode's itself has been modified)
  4490 00004B92 E80C0A0000          <1> 	call	setimod ; 25/05/2020
  4491                              <1> 	
  4492 00004B97 E952EFFFFF          <1> 	jmp	sysret
  4493                              <1> 
  4494                              <1> 	; 1: 
  4495                              <1> 		; jmp sysret4
  4496                              <1> 	; 3:
  4497                              <1> 		; jmp	error
  4498                              <1> 
  4499                              <1> isown:
  4500                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4501                              <1> 	; 06/11/2021
  4502                              <1> 	; 12/06/2021
  4503                              <1> 	; 01/05/2021
  4504                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4505                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4506                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4507                              <1> 	;
  4508                              <1> 	; 'isown' is given a file name (the 1st argument).
  4509                              <1> 	;  It find the i-number of that file via 'namei' 
  4510                              <1> 	;  then gets the i-node into core via 'iget'.
  4511                              <1> 	;  It then tests to see if the user is super user. 
  4512                              <1> 	;  If not, it checks to see if the user is owner of 
  4513                              <1> 	;  the file. If he is not an error occurs.
  4514                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4515                              <1> 	;  the inode has been modified and the 2nd argument of
  4516                              <1> 	;  the call is put in r2.
  4517                              <1> 	;
  4518                              <1> 	; INPUTS ->
  4519                              <1> 	;    arguments of syschmod and syschown calls
  4520                              <1> 	; OUTPUTS ->
  4521                              <1> 	;    u.uid - id of user
  4522                              <1> 	;    imod - set to a 1
  4523                              <1> 	;    r2 - contains second argument of the system call
  4524                              <1> 	;
  4525                              <1> 	;   ((AX=R2) output as 2nd argument)
  4526                              <1> 	;
  4527                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))
  4528                              <1> 	;
  4529                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4530                              <1> 	;; ! 2nd argument on top of stack !
  4531                              <1> 	;; 22/06/2015 - 32 bit modifications
  4532                              <1> 	;; 07/07/2013
  4533 00004B9C 891D[C4740000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4534 00004BA2 51                  <1> 	push 	ecx ;* ; 2nd argument
  4535                              <1> 	;;
  4536 00004BA3 E8C7FDFFFF          <1> 	call	namei
  4537                              <1> 		; jsr r0,namei / get its i-number
  4538                              <1>        ; Retro UNIX 8086 v1 modification !
  4539                              <1>        ; ax = 0 -> file not found 
  4540                              <1> 	;and	ax, ax
  4541                              <1> 	;jz	error
  4542                              <1> 	;jc	error ; 27/05/2013
  4543                              <1> 		; br error3
  4544 00004BA8 730F                <1> 	jnc	short isown1  ; 25/05/2020 (isown0 -> isown1)
  4545                              <1> 	; 'file not found !' error
  4546 00004BAA C705[1C750000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4546 00004BB2 0000                <1>
  4547 00004BB4 E915EFFFFF          <1> 	jmp	error
  4548                              <1> isown1:
  4549 00004BB9 E846080000          <1> 	call	iget
  4550                              <1> 		; jsr r0,iget / get i-node into core
  4551                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  4552                              <1> 	;; 06/11/2021
  4553                              <1> 	;jnc	short isown3
  4554                              <1> 	;mov	[u.error], eax
  4555                              <1> 	;jmp	error
  4556                              <1> ;isown3:
  4557                              <1> 	; check if it is super user ID
  4558                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4559 00004BBE 66A1[FA740000]      <1> 	mov	ax, [u.uid]
  4560 00004BC4 6609C0              <1> 	or	ax, ax
  4561                              <1> 	;mov	al, [u.uid] ; 02/08/2013
  4562                              <1> 	;or	al, al
  4563                              <1> 		; tstb u.uid / super user?
  4564                              <1> 	; 12/06/2021
  4565 00004BC7 7425                <1> 	jz	short isown2 ; 25/05/2020 (isown1 -> isown2)
  4566                              <1> 		; beq 1f / yes, branch
  4567                              <1> 	
  4568                              <1> 	; check user ID	(if same with file's owner)
  4569 00004BC9 663B05[48700000]    <1> 	cmp	ax, [i.uid] ; 09/01/2022
  4570                              <1> 	;cmp	al, [i.uid]
  4571                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4572                              <1> 				 ; / the file
  4573                              <1> 	;jne	error
  4574                              <1> 		; beq 1f / yes
  4575                              <1> 		; jmp error3 / no, error
  4576                              <1> 	;je	short isown2 ; 25/05/2020
  4577                              <1> 	; 01/05/2021
  4578 00004BD0 750D                <1> 	jne	short isown_err
  4579                              <1> 
  4580                              <1> 	; 01/05/2021
  4581                              <1> 	;mov	ax, [u.uid]
  4582                              <1> 	;or	ax, ax
  4583                              <1> 	;jz	short isown2 
  4584                              <1> 	;cmp	ax, [i.uid]
  4585                              <1> 	;;je	short isown2
  4586                              <1> 	;jne	short isown_err
  4587                              <1> 
  4588                              <1> 	; 01/05/2021
  4589                              <1> 	; ((Note: UNIX v7 x86 'chown', 'chmod' procedures
  4590                              <1> 	;    and their sub procedures do not check group ID))
  4591                              <1> 	; (('sys4.c', 'fio.c'))
  4592                              <1> 
  4593                              <1> 	; 01/05/2021
  4594                              <1> 	; check group ID (if same with group of file's owner)
  4595 00004BD2 A0[FE740000]        <1> 	mov	al, [u.gid]
  4596 00004BD7 3A05[4A700000]      <1> 	cmp	al, [i.gid]
  4597 00004BDD 740F                <1> 	je	short isown2
  4598                              <1> isown_err:
  4599 00004BDF C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER ; 11
  4599 00004BE7 0000                <1>
  4600                              <1> 			; 'permission denied !' error
  4601 00004BE9 E9E0EEFFFF          <1> 	jmp	error
  4602                              <1> 
  4603                              <1> 	; 25/05/2020
  4604                              <1> ;isown2: ; 1:
  4605                              <1> ;	call	setimod
  4606                              <1> ;		; jsr r0,setimod / indicates 
  4607                              <1> ;		;	       ; / i-node has been modified
  4608                              <1> isown2: 
  4609                              <1> 	; 25/05/2020
  4610 00004BEE 58                  <1> 	pop	eax ;* ; 2nd argument
  4611                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4612                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4613 00004BEF C3                  <1> 	retn
  4614                              <1> 
  4615                              <1> ;;arg:  ; < get system call arguments >
  4616                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4617                              <1> 	; of form:
  4618                              <1> 	;	sys 'routine' ; arg1
  4619                              <1> 	;		or
  4620                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4621                              <1> 	;		or
  4622                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4623                              <1> 	;	
  4624                              <1> 	; INPUTS ->
  4625                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4626                              <1> 	;	This pointers's value is actually the value of
  4627                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4628                              <1> 	;	made to process the sys instruction
  4629                              <1> 	;    r0 - contains the return address for the routine
  4630                              <1> 	;	that called arg. The data in the word pointer 
  4631                              <1> 	;	to by the return address is used as address
  4632                              <1> 	;	in which the extracted argument is stored
  4633                              <1> 	;    	
  4634                              <1> 	; OUTPUTS ->
  4635                              <1> 	;    'address' - contains the extracted argument 
  4636                              <1> 	;    u.sp+18 - is incremented by 2 
  4637                              <1> 	;    r1 - contains the extracted argument
  4638                              <1> 	;    r0 - points to the next instruction to be
  4639                              <1> 	;	 executed in the calling routine.
  4640                              <1> 	;
  4641                              <1>   
  4642                              <1> 	; mov u.sp,r1
  4643                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4644                              <1> 			; / into argument of arg2
  4645                              <1> 	; add $2,18.(r1) / point pc on stack 
  4646                              <1> 			      ; / to next system argument
  4647                              <1> 	; rts r0
  4648                              <1> 
  4649                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4650                              <1> 	; 'arg2' takes first argument in system call
  4651                              <1> 	;  (pointer to name of the file) and puts it in location
  4652                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4653                              <1> 	;  and on top of the stack
  4654                              <1> 	;	
  4655                              <1> 	; INPUTS ->
  4656                              <1> 	;    u.sp, r0
  4657                              <1> 	;    	
  4658                              <1> 	; OUTPUTS ->
  4659                              <1> 	;    u.namep
  4660                              <1> 	;    u.off 
  4661                              <1> 	;    u.off pushed on stack
  4662                              <1> 	;    r1
  4663                              <1> 	;
  4664                              <1> 
  4665                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4666                              <1> 				; / first arg in sys call
  4667                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4668                              <1> 				; / second arg in sys call
  4669                              <1> 	; mov r0,r1 / r0 points to calling routine
  4670                              <1> 	; mov (sp),r0 / put operation code back in r0
  4671                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4672                              <1> 			; / on stack
  4673                              <1> 	; jmp (r1) / return to calling routine
  4674                              <1> 
  4675                              <1> systime: ; / get time of year
  4676                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4677                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4678                              <1> 	;
  4679                              <1> 	; 20/06/2013
  4680                              <1> 	; 'systime' gets the time of the year.
  4681                              <1> 	; The present time is put on the stack.
  4682                              <1> 	;
  4683                              <1> 	; Calling sequence:
  4684                              <1> 	;	systime
  4685                              <1> 	; Arguments: -
  4686                              <1> 	;	
  4687                              <1> 	; Inputs: -
  4688                              <1> 	; Outputs: sp+2, sp+4 - present time
  4689                              <1> 	; ...............................................................
  4690                              <1> 	;	
  4691                              <1> 	; Retro UNIX 8086 v1 modification: 
  4692                              <1> 	;       'systime' system call will return to the user
  4693                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4694                              <1> 	;
  4695                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4696                              <1> 	;	system call for PC compatibility !!		 	
  4697                              <1> 
  4698 00004BF0 E810EAFFFF          <1> 	call 	epoch
  4699 00004BF5 A3[A8740000]        <1> 	mov 	[u.r0], eax
  4700                              <1> 		; mov s.time,4(sp)
  4701                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4702                              <1> 				   ; / on the stack
  4703                              <1> 		; br sysret4
  4704 00004BFA E9EFEEFFFF          <1> 	jmp	sysret 
  4705                              <1> 
  4706                              <1> sysstime: ; / set time
  4707                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4708                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4709                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4710                              <1> 	;
  4711                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4712                              <1> 	;
  4713                              <1> 	; Calling sequence:
  4714                              <1> 	;	sysstime
  4715                              <1> 	; Arguments: -
  4716                              <1> 	;	
  4717                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4718                              <1> 	; Outputs: -
  4719                              <1> 	; ...............................................................
  4720                              <1> 	;	
  4721                              <1> 	; Retro UNIX 8086 v1 modification: 
  4722                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4723                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4724                              <1> 	; 
  4725                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4726                              <1> 	;	to get sysstime system call arguments from the user;
  4727                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4728                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4729                              <1> 	;
  4730                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4731                              <1> 	;	system call for PC compatibility !!	
  4732                              <1> 
  4733                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4734 00004BFF 66833D[FA740000]00  <1> 	cmp	word [u.uid], 0 ; 16 bit user ID
  4735                              <1> 	;cmp	byte [u.uid], 0
  4736                              <1> 		; tstb u.uid / is user the super user
  4737                              <1> 	;ja	error
  4738                              <1> 		; bne error4 / no, error
  4739 00004C07 760F                <1> 	jna	short systime1
  4740                              <1> 	; 'permission denied !'
  4741 00004C09 C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4741 00004C11 0000                <1>
  4742 00004C13 E9B6EEFFFF          <1> 	jmp	error
  4743                              <1> systime1:
  4744                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4745                              <1> 	; EBX = unix (epoch) time (from user)
  4746 00004C18 89D8                <1> 	mov	eax, ebx
  4747 00004C1A E866EBFFFF          <1> 	call 	set_date_time
  4748                              <1> 		; mov 4(sp),s.time
  4749                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4750 00004C1F E9CAEEFFFF          <1> 	jmp	sysret
  4751                              <1> 		; br sysret4
  4752                              <1> 
  4753                              <1> sysbreak:
  4754                              <1> 	; 18/10/2015
  4755                              <1> 	; 07/10/2015
  4756                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4757                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4758                              <1> 	;
  4759                              <1> 	; 'sysbreak' sets the programs break points. 
  4760                              <1> 	; It checks the current break point (u.break) to see if it is
  4761                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4762                              <1> 	; even address (if it was odd) and the area between u.break
  4763                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4764                              <1> 	; in u.break and control is passed to 'sysret'.
  4765                              <1> 	;
  4766                              <1> 	; Calling sequence:
  4767                              <1> 	;	sysbreak; addr
  4768                              <1> 	; Arguments: -
  4769                              <1> 	;	
  4770                              <1> 	; Inputs: u.break - current breakpoint
  4771                              <1> 	; Outputs: u.break - new breakpoint 
  4772                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4773                              <1> 	; ...............................................................
  4774                              <1> 	;	
  4775                              <1> 	; Retro UNIX 8086 v1 modification:
  4776                              <1> 	;	The user/application program puts breakpoint address
  4777                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4778                              <1> 	; 	(argument transfer method 1)
  4779                              <1> 	;
  4780                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4781                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4782                              <1> 	;  NOTE:
  4783                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4784                              <1> 	;	'u.break' address) of user's memory for original unix's
  4785                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4786                              <1> 
  4787                              <1> 		; mov u.break,r1 / move users break point to r1
  4788                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4789                              <1> 		; blos 1f / yes, 1f
  4790                              <1> 	; 23/06/2015
  4791 00004C24 8B2D[D8740000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4792                              <1> 	;and	ebp, ebp
  4793                              <1> 	;jz	short sysbreak_3 
  4794                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4795                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4796 00004C2A 8B15[A0740000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4797 00004C30 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4798                              <1> 	; 07/10/2015
  4799 00004C33 891D[D8740000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4800                              <1> 	;
  4801 00004C39 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4802                              <1> 			   ; with top of user's stack (virtual!)
  4803 00004C3B 7327                <1> 	jnb	short sysbreak_3
  4804                              <1> 		; cmp r1,sp / is it the same or higher 
  4805                              <1> 			  ; / than the stack?
  4806                              <1> 		; bhis 1f / yes, 1f
  4807 00004C3D 89DE                <1> 	mov	esi, ebx
  4808 00004C3F 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4809 00004C41 7621                <1> 	jna	short sysbreak_3 
  4810                              <1> 	;push	ebx
  4811                              <1> sysbreak_1:
  4812 00004C43 89EB                <1> 	mov	ebx, ebp  
  4813 00004C45 E848E5FFFF          <1> 	call	get_physical_addr ; get physical address
  4814 00004C4A 0F825BFEFFFF        <1> 	jc	tr_addr_nm_err
  4815                              <1> 	; 18/10/2015
  4816 00004C50 89C7                <1> 	mov	edi, eax 
  4817 00004C52 29C0                <1> 	sub	eax, eax ; 0
  4818                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4819 00004C54 39CE                <1> 	cmp	esi, ecx
  4820 00004C56 7302                <1> 	jnb	short sysbreak_2
  4821 00004C58 89F1                <1> 	mov	ecx, esi
  4822                              <1> sysbreak_2:
  4823 00004C5A 29CE                <1> 	sub	esi, ecx
  4824 00004C5C 01CD                <1> 	add	ebp, ecx
  4825 00004C5E F3AA                <1> 	rep 	stosb
  4826 00004C60 09F6                <1> 	or	esi, esi
  4827 00004C62 75DF                <1> 	jnz	short sysbreak_1
  4828                              <1> 	;
  4829                              <1> 		; bit $1,r1 / is it an odd address
  4830                              <1> 		; beq 2f / no, its even
  4831                              <1> 		; clrb (r1)+ / yes, make it even
  4832                              <1> 	; 2: / clear area between the break point and the stack
  4833                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4834                              <1> 		; bhis 1f / yes, quit
  4835                              <1> 		; clr (r1)+ / clear word
  4836                              <1> 		; br 2b / go back
  4837                              <1> 	;pop	ebx
  4838                              <1> sysbreak_3: ; 1:
  4839                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4840                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4841                              <1> 			; / in u.break (set new break point)
  4842                              <1> 		; br sysret4 / br sysret
  4843 00004C64 E985EEFFFF          <1> 	jmp	sysret
  4844                              <1> 
  4845                              <1> maknod: 
  4846                              <1> 	; 14/02/2022
  4847                              <1> 	; 10/01/2022
  4848                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4849                              <1> 	; 06/11/2021 (Retro UNIX 386 v2)
  4850                              <1> 	; 15/08/2021
  4851                              <1> 	; 06/05/2021
  4852                              <1> 	; 02/05/2021
  4853                              <1> 	; 01/04/2021
  4854                              <1> 	; 27/03/2021
  4855                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  4856                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4857                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4858                              <1> 	;
  4859                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4860                              <1> 	; for this i-node in the current directory.
  4861                              <1> 	;
  4862                              <1> 	; INPUTS ->
  4863                              <1> 	;    r1 - contains mode
  4864                              <1> 	;    ii - current directory's i-number	
  4865                              <1> 	;    	
  4866                              <1> 	; OUTPUTS ->
  4867                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4868                              <1> 	;    i.flgs - flags in new i-node 
  4869                              <1> 	;    i.uid - filled with u.uid
  4870                              <1> 	;    i.nlks - 1 is put in the number of links
  4871                              <1> 	;    i.ctim - creation time
  4872                              <1> 	;    i.ctim+2 - modification time
  4873                              <1> 	;    imod - set via call to setimod
  4874                              <1> 	;	
  4875                              <1> 	; ((AX = R1)) input
  4876                              <1> 	;
  4877                              <1> 	; (Retro UNIX Prototype : 
  4878                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4879                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))
  4880                              <1> 
  4881                              <1> 	; 27/03/2021
  4882                              <1> 	; INPUT:
  4883                              <1>  	;	AX = mode
  4884                              <1> 	;
  4885                              <1> 	; ('maknod' is called by 'syscreat' and 'sysmkdir')
  4886                              <1> 	; (('syscreat' and 'sysmkdir' will set AX input))
  4887                              <1> 
  4888                              <1> 	; 27/03/2021
  4889                              <1> 	; Retro UNIX 386 v2 inode mode flags (ref: 'ux.s')
  4890                              <1> 	; for File Inode: (high byte)
  4891                              <1> 	;   IFREG - 1 = regular file (8000h)
  4892                              <1> 	;   IFDIR - 1 = directory (4000h)
  4893                              <1> 	;   IRSVD - 0 = reserved bit (2000h) ; Mounted flag for dirs
  4894                              <1> 	;   ILARG - large file addressing bit (1000h)
  4895                              <1> 	;   ISUID - set user id on exec (800h)
  4896                              <1> 	;   ISGID - set group id on exec (400h)
  4897                              <1> 	;   IEXTT - 1 = use extents (200h)
  4898                              <1> 	;   IREAD - read, owner (100h)
  4899                              <1> 	; for Device Inode: (high byte)
  4900                              <1> 	;   IFREG - 0 = device file (8000h)
  4901                              <1> 	;   IFBLK - 1 = block device (4000h)
  4902                              <1> 	;   IFCHR - character special (2000h) -always 1-
  4903                              <1> 	;   IFIFO - fifo special (1000h)
  4904                              <1> 	;   IPIPE - pipe special (800h) ; 07/02/2020
  4905                              <1> 	;   IREDIR - redirected (400h)  ; 07/02/2020
  4906                              <1> 	;   IEXTR - 1 = external device driver (200h)
  4907                              <1> 	;   IREAD - read, owner (100h)
  4908                              <1> 
  4909                              <1> 	;; / r1 contains the mode
  4910                              <1> 	;or 	ah, 80h	; 10000000b
  4911                              <1> 	;	; bis $100000,r1 / allocate flag set
  4912                              <1> 
  4913                              <1> 	; 14/02/2022
  4914                              <1> 	; input ->
  4915                              <1> 	;   [u.namep] points to the file name address
  4916                              <1> 	;	     (in the user's memory space)
  4917                              <1> 	;   [u.dirp] points to empty slot in the directory
  4918                              <1> 
  4919                              <1> 	; high 3 bit will be checked here
  4920                              <1> 	; 	(ref: unix v7 x86 source, iget.c)
  4921                              <1> 
  4922                              <1> ;	; 27/03/2021
  4923                              <1> ;	test	ah, 0E0h ; 80h+40h+20h
  4924                              <1> ;	jnz	short maknod0	
  4925                              <1> ;
  4926                              <1> ;	; ('syscreat' clears ILARG & IEXTT bits)
  4927                              <1> ;	;and	ah, ~0Ch ; clear ILARG & IEXTT bits
  4928                              <1> ;	;	; user can set ISUID & ISGID bits
  4929                              <1> ;
  4930                              <1> ;	or	ah, 80h ; IFREG
  4931                              <1> ;maknod0:
  4932 00004C69 50                  <1> 	push	eax ; ***** ; 27/03/2021 (32 bit push, pop)
  4933                              <1> 		; mov r1,-(sp) / put mode on stack
  4934                              <1> 	; 31/07/2013
  4935                              <1> 	;mov	ax, [ii] ; move current i-number to AX/r1
  4936                              <1> 	;	; mov ii,r1 / move current i-number to r1
  4937                              <1> 	;mov	dl, 1 ; owner flag mask
  4938                              <1> 	; 15/08/2021
  4939                              <1> 	;movzx	eax, word [ii] ; move current i-number to EAX
  4940                              <1> 	; 09/01/2022
  4941 00004C6A A1[84740000]        <1> 	mov	eax, [ii] ; move current i-number to EAX
  4942                              <1> 	; 25/03/2021
  4943 00004C6F 66BA8000            <1> 	mov	dx, 80h	; IWRITE - write,owner
  4944 00004C73 E876080000          <1> 	call	access	
  4945                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4946                              <1> 	; 15/08/2021
  4947                              <1> 	; NOTE: cpu will not return here if there is a permission error
  4948                              <1> 	;	(it will jump to 'error' address from/in 'access')
  4949                              <1> 	
  4950 00004C78 50                  <1> 	push	eax ; **** ; 27/03/2021 (32 bit push, pop)
  4951                              <1> 		; mov r1,-(sp) / put i-number on stack
  4952                              <1> 	;mov	ax, 40
  4953                              <1> 	;	; mov $40.,r1 / r1 = 40
  4954                              <1> 	; 27/03/2021
  4955 00004C79 31C0                <1> 	xor	eax, eax
  4956                              <1> 	;;dec	ax ; 0FFFFh
  4957                              <1> 	; 15/08/2021
  4958                              <1> 	;dec	eax ; 0FFFFFFFFh
  4959                              <1> 	; 01/04/2021
  4960                              <1> ;maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4961                              <1> 	;;inc	ax
  4962                              <1> 	;	; inc r1 / r1 = r1 + 1
  4963                              <1> 	; 15/08/2021
  4964                              <1> 	;inc	eax
  4965                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  4966                              <1> 	; eax = 0 -> start from first free inode
  4967                              <1> 	; eax > 0 -> locate this inode on the inode map buffer
  4968                              <1> 	; NOTE:
  4969                              <1> 	; Retro UNIX 386 v2 'imap' is mostly different than v1 'imap'
  4970                              <1> 	; ('imap' will not check inode table)
  4971 00004C7B E86F0A0000          <1> 	call	imap
  4972                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4973                              <1> 			    ; /	inode map in r2 & m
  4974                              <1> 	; 09/01/2022
  4975                              <1> 	; (cpu will not return here if there would be an eror in imap)
  4976                              <1> 	; 15/08/2021
  4977                              <1> 	;jc	short maknod_err
  4978                              <1> 
  4979                              <1> 	; DX (MQ) has a 1 in the calculated bit position
  4980                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4981                              <1> 
  4982                              <1> 	; 06/11/2021
  4983                              <1> 	; ebp = superblock buffer address
  4984                              <1> 	; eax = inode number
  4985                              <1> 	; 10/01/2022
  4986                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  4987                              <1> 	;		of current IMAP sector	
  4988                              <1> 
  4989                              <1> 	; 27/03/2021
  4990                              <1> 	; If cpu is here, there is not an error
  4991                              <1> 	; and EBX points to inode map buffer
  4992                              <1> 	; DL has 1 at bit position which is for free inode
  4993                              <1> 	; (E)AX = inode number
  4994                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4995                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  4996                              <1> 
  4997                              <1> 	; 15/08/2021
  4998                              <1> maknod1:
  4999                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  5000                              <1> 	;	       Inode count must be checked here
  5001                              <1> 	; (Original UNIX v1 did not check inode count here !?)
  5002 00004C80 8413                <1> 	test	[ebx], dl
  5003                              <1> 		; bitb mq,(r2) / is the i-node active
  5004                              <1> 	;jnz	short maknod1
  5005                              <1> 	;	; bne 1b / yes, try the next one
  5006                              <1> 	; 15/08/2021
  5007 00004C82 7408                <1> 	jz	short maknod3 ; free inode (inactive inode)
  5008                              <1> maknod2:
  5009 00004C84 40                  <1> 	inc	eax
  5010 00004C85 E8890A0000          <1> 	call	imap_x ; next call to imap (bypass 1st call code)
  5011                              <1> 	; 10/01/2022
  5012                              <1> 	; (cpu will/would not return here 
  5013                              <1> 	;  if there is/was an error in 'imap_x')
  5014                              <1> 	;jnc	short maknod1
  5015 00004C8A EBF4                <1> 	jmp	short maknod1
  5016                              <1> 
  5017                              <1> 	; 14/02/2022
  5018                              <1> ;maknod_err:
  5019                              <1> ;	; 15/08/2021
  5020                              <1> ;	;pop	edx  ; two pops for stack alignment
  5021                              <1> ;	;pop	edx  ; (may not be needed while jumping to 'error')
  5022                              <1> ;	mov	[u.error], eax
  5023                              <1> ;	jmp	error
  5024                              <1> maknod3:
  5025                              <1> 	; 10/01/2022
  5026                              <1> 	; ebp = superblock buffer address
  5027                              <1> 	; eax = (free) inode number
  5028                              <1> 	; [ebp+SB.ImapBuffer] = physical block/sector number
  5029                              <1> 	;		of current IMAP sector
  5030                              <1> 	; EBX = buffer address/offset for relevant alloc byte
  5031                              <1> 	;  DL has 1 at bit position which is for free inode
  5032                              <1> 	;
  5033                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  5034                              <1> 
  5035                              <1> 	;mov	[ebp+SB.LastInode], eax ; (free) inode number
  5036                              <1> 
  5037 00004C8C 50                  <1> 	push	eax ; ***
  5038 00004C8D 51                  <1> 	push	ecx ; **
  5039 00004C8E 52                  <1> 	push	edx ; *
  5040                              <1> 
  5041 00004C8F 8B457C              <1> 	mov	eax, [ebp+SB.ImapBuffer]
  5042                              <1> 
  5043 00004C92 E8E4140000          <1> 	call	wslot
  5044                              <1> 	; ebx = buffer data address (write operation bit is set)
  5045                              <1> 	; eax = physical sector number
  5046                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  5047                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  5048                              <1> 
  5049                              <1> 	;mov	[ebp+SB.ImapBuffer], ebx
  5050                              <1> 			; save inode map buffer address
  5051 00004C97 5A                  <1> 	pop	edx ; *
  5052 00004C98 59                  <1> 	pop	ecx ; **
  5053 00004C99 01CB                <1> 	add	ebx, ecx ; + byte offset (for allocation bit pos)	
  5054                              <1> 
  5055                              <1> 	; set allocation bit (for this new inode) ; 10/01/2022 
  5056 00004C9B 0813                <1> 	or	[ebx], dl
  5057                              <1> 		; bisb mq,(r2) / no, make it active 
  5058                              <1> 			     ; / (put a 1 in the bit map)
  5059                              <1> 	;push	ebp ; @
  5060 00004C9D E8F5140000          <1> 	call	dskwr ; writes the 1st buffer to sector
  5061                              <1> 		      ; (at the beginning/head of the buffer chain)
  5062                              <1> 	;pop	ebp ; @
  5063                              <1> 
  5064                              <1> 	; if we are here, buffer has been written to disk successfully 
  5065                              <1> 	; (otherwise cpu would jump to 'error' address)
  5066                              <1> 
  5067                              <1> 	; set superblock modified flag
  5068 00004CA2 BA[9C740000]        <1> 	mov	edx, smod
  5069 00004CA7 F605[89740000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  5070 00004CAE 7401                <1> 	jz	short maknod4 ; no, root device
  5071                              <1> 	; yes, mounted device
  5072                              <1> 	;mov	edx, mmod
  5073 00004CB0 42                  <1> 	inc	edx ; edx = offset mmod
  5074                              <1> maknod4: 
  5075 00004CB1 FE02                <1> 	inc	byte [edx] ; superblock modified !
  5076                              <1> 
  5077                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5078                              <1> 	;;
  5079                              <1> 	;; 27/03/2021
  5080                              <1> 	;; (ref: 'UNIXHDCP.ASM', 'mak_nod', 18/01/2020)
  5081                              <1> 	;or	byte [smod], 2 ; inode map modified
  5082                              <1> 	;; 01/04/2021
  5083                              <1> 	;;or	byte [imapbuf_hdr+bufhdr.status], 2
  5084                              <1> 	;or	byte [imapbuf_hdr], 2 ; set modified flag bit
  5085                              <1> 	; 02/05/2021
  5086                              <1> 	;or	byte [esi+ldrv.b_status], 2 ; inode map modified
  5087                              <1> 	; 15/08/2021
  5088                              <1> 	; 06/05/2021
  5089                              <1> 	;or	byte [esi+ldrv.status], 2 ; inode map modified
  5090                              <1> 	;;or	byte [sysbuf_hdr], 2 ; set modified flag bit
  5091                              <1> 	
  5092                              <1> 	;mov	eax, [ebp+SB.LastInode] ; (free) inode number
  5093                              <1> 	;push	eax ; ***
  5094 00004CB3 8B0424              <1> 	mov	eax, [esp] ; ***
  5095 00004CB6 40                  <1> 	inc	eax ; next inode number 
  5096                              <1> 		    ; (free inode search start value)
  5097 00004CB7 894534              <1> 	mov	[ebp+SB.FirstFreeIno], eax
  5098 00004CBA E8A0150000          <1> 	call	get_system_time
  5099                              <1> 		; eax = current time (as unix epoch time)
  5100 00004CBF 89455C              <1> 	mov	[ebp+SB.ModifTime], eax
  5101 00004CC2 58                  <1> 	pop	eax ; *** ; inode number
  5102                              <1> 	;;
  5103 00004CC3 E83C070000          <1> 	call	iget
  5104                              <1> 		; jsr r0,iget / get i-node into core
  5105                              <1> 	; 09/01/2022
  5106                              <1> 	;  (If cpu is here, there was/is not an error!)
  5107                              <1> 	; 06/11/2021
  5108                              <1> 	;jc	short maknod_err
  5109                              <1> 	
  5110                              <1> 	;test	word [i.flgs], 8000h 
  5111                              <1> 	;	; tst i.flgs / is i-node already allocated
  5112                              <1> 	;jnz	short maknod1	
  5113                              <1> 	;	; blt 1b / yes, look for another one
  5114                              <1> 	; 27/03/2021
  5115                              <1> 	; (Retro UNIX 386 v2 inode flags) 
  5116 00004CC8 F605[45700000]E0    <1> 	test	byte [i.flgs+1], 0E0h ; 80h+40h+20h
  5117                              <1> 	;jnz	short maknod1 ; i-node already allocated
  5118                              <1> 	;		      ; (as it is in inode table)
  5119                              <1> 	; 15/08/2021
  5120 00004CCF 75B3                <1> 	jnz	short maknod2 ; defective inode map !?
  5121                              <1> 
  5122                              <1> 	; AX = free inode number
  5123 00004CD1 66A3[E0740000]      <1> 	mov	[u.dirbuf], ax
  5124                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  5125 00004CD7 58                  <1> 	pop	eax ; **** ; 27/03/2021 (32 bit push, pop)
  5126                              <1> 		; mov (sp)+,r1 / get current i-number back
  5127 00004CD8 E827070000          <1> 	call	iget
  5128                              <1> 		; jsr r0,iget / get i-node in core
  5129                              <1> 	; 09/01/2022
  5130                              <1> 	; 06/11/2021
  5131                              <1> 	;jc	short maknod_err
  5132                              <1> 
  5133                              <1> 	; 14/02/2022
  5134                              <1> 	; here..
  5135                              <1> 	;  [u.namep] points to the file name address
  5136                              <1> 	;	     (in the user's memory space)
  5137                              <1> 	;  [u.dirp] points to empty slot in the directory
  5138                              <1> 
  5139 00004CDD E867F7FFFF          <1> 	call	mkdir
  5140                              <1> 		; jsr r0,mkdir / make a directory entry 
  5141                              <1> 			     ; / in current directory
  5142                              <1> 	; 09/01/2022
  5143                              <1> 	;  (If cpu is here, there was/is not an error in 'mkdir'!)
  5144                              <1> 	; 06/11/2021
  5145                              <1> 	;jc	short maknod_err
  5146                              <1> 	
  5147                              <1> 	; (eax = 0)
  5148                              <1> 	;movzx	eax, [u.difbuf] ; 06/11/2021
  5149 00004CE2 66A1[E0740000]      <1> 	mov	ax, [u.dirbuf]
  5150                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  5151 00004CE8 E817070000          <1> 	call	iget
  5152                              <1> 		; jsr r0,iget / get it into core
  5153                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  5154                              <1> 	; 09/01/2022
  5155                              <1> 	; 06/11/2021
  5156                              <1> 	;jc	short maknod_err
  5157                              <1> 
  5158                              <1> 	;mov	ecx, 8
  5159                              <1> 	; 27/03/2021
  5160 00004CED 31C9                <1> 	xor	ecx, ecx 
  5161 00004CEF B110                <1> 	mov	cl, 16 ; 64 bit inodes
  5162 00004CF1 31C0                <1> 	xor	eax, eax ; 0
  5163 00004CF3 BF[44700000]        <1> 	mov	edi, inode 
  5164 00004CF8 F3AB                <1> 	rep	stosd
  5165                              <1> 	;
  5166                              <1> 	;pop	word [i.flgs]
  5167                              <1> 	;	; mov (sp)+,i.flgs / fill flags
  5168                              <1> 	; 27/03/2021 (32 bit push, pop)
  5169 00004CFA 58                  <1> 	pop	eax ; *****
  5170 00004CFB 66A3[44700000]      <1> 	mov	[i.flgs], ax
  5171                              <1> 
  5172                              <1> 	;mov 	cl, [u.uid] ; 02/08/2013
  5173                              <1> 	;mov 	[i.uid], cl
  5174                              <1> 	;	; movb u.uid,i.uid / user id
  5175                              <1> 	; 15/08/2021
  5176                              <1> 	; 27/03/2021
  5177 00004D01 8A0D[FE740000]      <1> 	mov	cl, [u.gid] ; 8 bit group ID ; 15/08/2021
  5178 00004D07 880D[4A700000]      <1> 	mov	[i.gid], cl 	
  5179 00004D0D 668B0D[FA740000]    <1> 	mov	cx, [u.uid] ; 16 bit user ID
  5180 00004D14 66890D[48700000]    <1> 	mov	[i.uid], cx	
  5181                              <1> 
  5182 00004D1B C605[46700000]01    <1> 	mov     byte [i.nlks], 1
  5183                              <1> 		; movb $1,i.nlks / 1 link
  5184                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  5185                              <1> 	;mov	eax, [s.time]
  5186                              <1> 	;mov 	[i.ctim], eax
  5187                              <1> 	 	; mov s.time,i.ctim / time created
  5188                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  5189                              <1> 	; Retro UNIX 8086 v1 modification !
  5190                              <1> 	; i.ctime=0, i.ctime+2=0 and
  5191                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  5192                              <1> 	;call	setimod
  5193                              <1> 	;	; jsr r0,setimod / set modified flag
  5194                              <1> 	;retn
  5195                              <1> 	;	; rts r0 / return
  5196                              <1> 	; 27/03/2021
  5197 00004D22 E97C080000          <1> 	jmp	setimod
  5198                              <1> 
  5199                              <1> sysseek: ; / moves read write pointer in an fsp entry
  5200                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5201                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5202                              <1> 	;
  5203                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  5204                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  5205                              <1> 	; The file descriptor refers to a file open for reading or
  5206                              <1> 	; writing. The read (or write) pointer is set as follows:
  5207                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  5208                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  5209                              <1> 	;	  current location plus offset.
  5210                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  5211                              <1> 	;	  size of file plus offset.
  5212                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  5213                              <1> 	;
  5214                              <1> 	; Calling sequence:
  5215                              <1> 	;	sysseek; offset; ptrname
  5216                              <1> 	; Arguments:
  5217                              <1> 	;	offset - number of bytes desired to move 
  5218                              <1> 	;		 the r/w pointer
  5219                              <1> 	;	ptrname - a switch indicated above
  5220                              <1> 	;
  5221                              <1> 	; Inputs: r0 - file descriptor 
  5222                              <1> 	; Outputs: -
  5223                              <1> 	; ...............................................................
  5224                              <1> 	;	
  5225                              <1> 	; Retro UNIX 8086 v1 modification: 
  5226                              <1> 	;       'sysseek' system call has three arguments; so,
  5227                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  5228                              <1> 	;	* 2nd argument, offset is in CX register
  5229                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  5230                              <1> 	;	
  5231                              <1> 
  5232 00004D27 E822000000          <1> 	call	seektell
  5233                              <1> 	; AX = u.count
  5234                              <1> 	; BX = *u.fofp
  5235                              <1> 		; jsr r0,seektell / get proper value in u.count
  5236                              <1> 		; add u.base,u.count / add u.base to it
  5237 00004D2C 0305[CC740000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  5238 00004D32 8903                <1> 	mov	[ebx], eax
  5239                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  5240 00004D34 E9B5EDFFFF          <1> 	jmp	sysret
  5241                              <1> 		; br sysret4
  5242                              <1> 
  5243                              <1> systell: ; / get the r/w pointer
  5244                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5245                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5246                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5247                              <1> 	;
  5248                              <1> 	; Retro UNIX 8086 v1 modification:
  5249                              <1> 	; ! 'systell' does not work in original UNIX v1,
  5250                              <1> 	; 	    it returns with error !
  5251                              <1> 	; Inputs: r0 - file descriptor 
  5252                              <1> 	; Outputs: r0 - file r/w pointer
  5253                              <1> 
  5254                              <1> 	;xor	ecx, ecx ; 0
  5255                              <1> 	;mov	edx, 1 ; 05/08/2013
  5256                              <1> 	; 09/01/2022
  5257 00004D39 29D2                <1> 	sub	edx, edx
  5258 00004D3B FEC2                <1> 	inc	dl
  5259                              <1> 	; edx = 1
  5260                              <1> 	;call 	seektell
  5261 00004D3D E812000000          <1> 	call 	seektell0 ; 05/08/2013
  5262                              <1> 	;mov	ebx, [u.fofp]
  5263 00004D42 8B03                <1> 	mov	eax, [ebx]
  5264 00004D44 A3[A8740000]        <1> 	mov	[u.r0], eax
  5265 00004D49 E9A0EDFFFF          <1> 	jmp	sysret
  5266                              <1> 
  5267                              <1> ; Original unix v1 'systell' system call:
  5268                              <1> 		; jsr r0,seektell
  5269                              <1> 		; br error4
  5270                              <1> 
  5271                              <1> seektell:
  5272                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5273                              <1> 	; 06/11/2021
  5274                              <1> 	; 12/06/2021
  5275                              <1> 	; 06/05/2021 (Retro UNIX 386 v2)
  5276                              <1> 	; 03/01/2016
  5277                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5278                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5279                              <1> 	;
  5280                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  5281                              <1> 	; call in u.base and u.count. It then gets the i-number of
  5282                              <1> 	; the file from the file descriptor in u.r0 and by calling
  5283                              <1> 	; getf. The i-node is brought into core and then u.count
  5284                              <1> 	; is checked to see it is a 0, 1, or 2.
  5285                              <1> 	; If it is 0 - u.count stays the same
  5286                              <1> 	;          1 - u.count = offset (u.fofp)
  5287                              <1> 	;	   2 - u.count = i.size (size of file)
  5288                              <1> 	; 	 		
  5289                              <1> 	; !! Retro UNIX 8086 v1 modification:
  5290                              <1> 	;	Argument 1, file descriptor is in BX;
  5291                              <1> 	;	Argument 2, offset is in CX;
  5292                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  5293                              <1> 	;
  5294                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  5295                              <1> 	; call 	arg
  5296                              <1> 	;
  5297                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  5298                              <1> 	;
  5299 00004D4E 890D[CC740000]      <1> 	mov 	[u.base], ecx ; offset
  5300                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  5301                              <1> 	; 09/01/2022
  5302                              <1> 	; ebx = file descriptor (0 to 9)
  5303                              <1> seektell0:
  5304 00004D54 8915[D0740000]      <1> 	mov 	[u.count], edx
  5305                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  5306                              <1> 	;mov	ax, bx
  5307                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  5308                              <1> 			     ; / (index in u.fp list)
  5309                              <1> 	; 12/06/2021
  5310                              <1> 	; BX = file descriptor (file number)
  5311 00004D5A E8DAFBFFFF          <1> 	call	getf
  5312                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  5313                              <1> 	; 09/01/2022
  5314 00004D5F 09C0                <1> 	or	eax, eax
  5315                              <1> 	;or	ax, ax ; i-number of the file
  5316                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  5317                              <1> 		             ; / put it on the stack
  5318                              <1> 	;jz	error
  5319                              <1> 		; beq error4 / if i-number is 0, not active so error
  5320 00004D61 750F                <1> 	jnz	short seektell1
  5321 00004D63 C705[1C750000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  5321 00004D6B 0000                <1>
  5322 00004D6D E95CEDFFFF          <1> 	jmp	error
  5323                              <1> seektell1:
  5324                              <1> 	; 06/05/2021
  5325                              <1> 	;push	eax
  5326                              <1> 	;cmp	ah, 80h
  5327                              <1> 	;jb	short seektell2
  5328                              <1> 	;	; bgt .+4 / if its positive jump
  5329                              <1> 	;neg	ax
  5330                              <1> 	;	; neg r1 / if not make it positive
  5331                              <1> seektell2:
  5332 00004D72 E88D060000          <1> 	call	iget
  5333                              <1> 		; jsr r0,iget / get its i-node into core
  5334                              <1> 	; 09/01/2022
  5335                              <1> 	; (if there is/was an error in 'iget', cpu will not come here)
  5336                              <1> 	;; 06/11/2021
  5337                              <1> 	;jnc	short seektell6
  5338                              <1> 	;mov	[u.error], eax
  5339                              <1> 	;jmp	error
  5340                              <1> seektell6:
  5341 00004D77 8B1D[BC740000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  5342 00004D7D 803D[D0740000]01    <1> 	cmp	byte [u.count], 1
  5343                              <1> 		; cmp u.count,$1 / is ptr name =1
  5344 00004D84 7705                <1> 	ja	short seektell3
  5345                              <1> 		; blt 2f / no its zero
  5346 00004D86 7409                <1> 	je	short seektell4
  5347                              <1> 		; beq 1f / yes its 1
  5348 00004D88 31C0                <1> 	xor	eax, eax
  5349                              <1> 	;jmp	short seektell5
  5350 00004D8A C3                  <1> 	retn
  5351                              <1> seektell3:
  5352                              <1> 	; 03/01/2016
  5353                              <1> 	;;movzx	eax, word [i.size]
  5354                              <1> 	;mov   	ax, [i.size]
  5355                              <1> 	;	; mov i.size,u.count /  put number of bytes 
  5356                              <1> 	;			; / in file in u.count
  5357                              <1> 	;;jmp	short seektell5
  5358                              <1> 	;	; br 2f
  5359                              <1> 	; 06/05/2021 - Retro UNIX 386 v2
  5360 00004D8B A1[4C700000]        <1> 	mov	eax, [i.size]
  5361 00004D90 C3                  <1> 	retn
  5362                              <1> seektell4: ; 1: / ptrname =1
  5363                              <1> 	;mov	ebx, [u.fofp]
  5364 00004D91 8B03                <1> 	mov	eax, [ebx]
  5365                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  5366                              <1> ;seektell5: ; 2: / ptrname =0
  5367                              <1> 	;mov	[u.count], eax
  5368                              <1> 	;pop	eax 
  5369                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  5370 00004D93 C3                  <1> 	retn
  5371                              <1> 		; rts r0
  5372                              <1> 
  5373                              <1> sysintr: ; / set interrupt handling
  5374                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5375                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5376                              <1> 	;
  5377                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  5378                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  5379                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  5380                              <1> 	; If one does the interrupt character in the tty buffer is
  5381                              <1> 	; cleared and 'sysret'is called. If one does not exits
  5382                              <1> 	; 'sysret' is just called.	
  5383                              <1> 	;
  5384                              <1> 	; Calling sequence:
  5385                              <1> 	;	sysintr; arg
  5386                              <1> 	; Argument:
  5387                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  5388                              <1> 	;	    - if 1, intterupts cause their normal result
  5389                              <1> 	;		 i.e force an exit.
  5390                              <1> 	;	    - if arg is a location within the program,
  5391                              <1> 	;		control is passed to that location when
  5392                              <1> 	;		an interrupt occurs.	
  5393                              <1> 	; Inputs: -
  5394                              <1> 	; Outputs: -
  5395                              <1> 	; ...............................................................
  5396                              <1> 	;	
  5397                              <1> 	; Retro UNIX 8086 v1 modification: 
  5398                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  5399                              <1> 	;	then branches into sysquit.
  5400                              <1> 	;
  5401 00004D94 66891D[F4740000]    <1> 	mov	[u.intr], bx
  5402                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  5403                              <1> 		; br 1f / go into quit routine
  5404 00004D9B E94EEDFFFF          <1> 	jmp	sysret
  5405                              <1> 
  5406                              <1> sysquit:
  5407                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5408                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5409                              <1> 	;
  5410                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  5411                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  5412                              <1> 	; tty exists. If one does the interrupt character in the tty
  5413                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  5414                              <1> 	; 'sysret' is just called.	
  5415                              <1> 	;
  5416                              <1> 	; Calling sequence:
  5417                              <1> 	;	sysquit; arg
  5418                              <1> 	; Argument:
  5419                              <1> 	;	arg - if 0, this call disables quit signals from the
  5420                              <1> 	;		typewriter (ASCII FS)
  5421                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  5422                              <1> 	;		cease and a core image to be produced.
  5423                              <1> 	;		 i.e force an exit.
  5424                              <1> 	;	    - if arg is an address in the program,
  5425                              <1> 	;		a quit causes control to sent to that
  5426                              <1> 	;		location.	
  5427                              <1> 	; Inputs: -
  5428                              <1> 	; Outputs: -
  5429                              <1> 	; ...............................................................
  5430                              <1> 	;	
  5431                              <1> 	; Retro UNIX 8086 v1 modification: 
  5432                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  5433                              <1> 	;	then branches into 'sysret'.
  5434                              <1> 	;
  5435 00004DA0 66891D[F6740000]    <1> 	mov	[u.quit], bx
  5436 00004DA7 E942EDFFFF          <1> 	jmp	sysret
  5437                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  5438                              <1> 	;1:
  5439                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  5440                              <1> 			      ; / to r1
  5441                              <1> 		; beq sysret4 / return to user
  5442                              <1> 		; clrb 6(r1) / clear the interrupt character 
  5443                              <1> 			   ; / in the tty buffer
  5444                              <1> 		; br sysret4 / return to user
  5445                              <1> 
  5446                              <1> syssetuid: ; / set process id
  5447                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5448                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5449                              <1> 	;		(16 bit uid)
  5450                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5451                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  5452                              <1> 	;
  5453                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  5454                              <1> 	; to the process id in (u.r0). Both the effective user u.uid
  5455                              <1> 	; and the real user u.ruid are set to this. 
  5456                              <1> 	; Only the super user can make this call.	
  5457                              <1> 	;
  5458                              <1> 	; Calling sequence:
  5459                              <1> 	;	syssetuid
  5460                              <1> 	; Arguments: -
  5461                              <1> 	;
  5462                              <1> 	; Inputs: (u.r0) - contains the process id.
  5463                              <1> 	; Outputs: -
  5464                              <1> 	; ...............................................................
  5465                              <1> 	;	
  5466                              <1> 	; Retro UNIX 8086 v1 modification: 
  5467                              <1> 	;       BL contains the (new) user ID of the current process
  5468                              <1> 
  5469                              <1> 	; 27/03/2021
  5470                              <1> 	; INPUT:
  5471                              <1> 	;    BX = (new) user ID
  5472                              <1> 
  5473                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  5474                              <1> 	;cmp	bl, [u.ruid] 
  5475                              <1> 	;	; cmpb r1,u.ruid / is it equal to the real user 
  5476                              <1> 			       ; / id number
  5477                              <1> 	; 27/03/2021
  5478 00004DAC 663B1D[FC740000]    <1> 	cmp	bx, [u.ruid]
  5479 00004DB3 7420                <1> 	je	short setuid1
  5480                              <1> 		; beq 1f / yes
  5481                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  5482                              <1> 	;	; tstb u.uid / no, is current user the super user?
  5483                              <1> 	;;ja	error
  5484                              <1> 	;	; bne error4 / no, error
  5485                              <1> 	; 27/03/2021
  5486 00004DB5 66833D[FA740000]00  <1> 	cmp	word [u.uid], 0 
  5487 00004DBD 760F                <1> 	jna	short setuid0
  5488                              <1> setuid_err:
  5489                              <1> setgid_err:
  5490 00004DBF C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  5490 00004DC7 0000                <1>
  5491                              <1> 				;  'permission denied !' error
  5492 00004DC9 E900EDFFFF          <1> 	jmp	error
  5493                              <1> setuid0:
  5494                              <1> 	;mov	[u.ruid], bl
  5495                              <1> 	; 27/03/2021
  5496 00004DCE 66891D[FC740000]    <1> 	mov	[u.ruid], bx
  5497                              <1> setuid1: ; 1:
  5498                              <1> 	;mov	[u.uid], bl ; 02/08/2013
  5499                              <1> 	;	; movb r1,u.uid / put process id in u.uid
  5500                              <1> 	;	; movb r1,u.ruid / put process id in u.ruid
  5501                              <1> 	; 27/03/2021
  5502 00004DD5 66891D[FA740000]    <1> 	mov	[u.uid], bx
  5503 00004DDC E90DEDFFFF          <1> 	jmp	sysret
  5504                              <1> 		; br sysret4 / system return
  5505                              <1> 
  5506                              <1> sysgetuid: ; < get user id >
  5507                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5508                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5509                              <1> 	;		(16 bit uid)
  5510                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5511                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5512                              <1> 	;
  5513                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  5514                              <1> 	; The real user ID identifies the person who is logged in,
  5515                              <1> 	; in contradistinction to the effective user ID, which
  5516                              <1> 	; determines his access permission at each moment. It is thus
  5517                              <1> 	; useful to programs which operate using the 'set user ID'
  5518                              <1> 	; mode, to find out who invoked them.	
  5519                              <1> 	;
  5520                              <1> 	; Calling sequence:
  5521                              <1> 	;	syssetuid
  5522                              <1> 	; Arguments: -
  5523                              <1> 	;
  5524                              <1> 	; Inputs: -
  5525                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  5526                              <1> 	; ...............................................................
  5527                              <1> 	;	
  5528                              <1> 	; Retro UNIX 8086 v1 modification: 
  5529                              <1> 	;       AL contains the real user ID at return.
  5530                              <1> 	;
  5531                              <1> 	;;movzx eax, byte [u.ruid]
  5532                              <1> 	; 27/03/2021
  5533                              <1> 	;movzx	eax, word [u.ruid]
  5534                              <1> 	; 09/01/2022
  5535 00004DE1 66A1[FC740000]      <1> 	mov	ax, [u.ruid]
  5536 00004DE7 A3[A8740000]        <1> 	mov	[u.r0], eax
  5537                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  5538 00004DEC E9FDECFFFF          <1> 	jmp	sysret
  5539                              <1> 		; br sysret4 / systerm return, sysret
  5540                              <1> 
  5541                              <1> syssetgid: ; set group id
  5542                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5543                              <1> 	; 02/04/2021
  5544                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5545                              <1> 	;
  5546                              <1> 	; 'syssetgid' sets the user's group id (u.gid) 
  5547                              <1> 	;  of the current process to the process id in (u.r0).
  5548                              <1> 	;  Both the effective user u.gid and the real user
  5549                              <1> 	;  u.rgid are set to this. 
  5550                              <1> 	;  Only the super user can make this call.	
  5551                              <1> 	
  5552                              <1> 	; INPUT:
  5553                              <1> 	;	BL = (new) group ID
  5554                              <1> 	; OUTPUT:
  5555                              <1> 	;	-
  5556                              <1> 
  5557 00004DF1 3A1D[FF740000]      <1> 	cmp	bl, [u.rgid] 
  5558 00004DF7 7410                <1> 	je	short setgid1
  5559                              <1> 
  5560                              <1> 	;cmp	byte [u.uid], 0
  5561                              <1> 	; 02/04/2021
  5562 00004DF9 66833D[FA740000]00  <1> 	cmp	word [u.uid], 0
  5563 00004E01 77BC                <1> 	ja	short setgid_err
  5564                              <1> setgid0:
  5565 00004E03 881D[FF740000]      <1> 	mov	[u.rgid], bl
  5566                              <1> setgid1: ; 1:
  5567 00004E09 881D[FE740000]      <1> 	mov	[u.gid], bl
  5568 00004E0F E9DAECFFFF          <1> 	jmp	sysret
  5569                              <1> 
  5570                              <1> sysgetgid: ; < get group id > (& user ID)
  5571                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5572                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5573                              <1> 	;
  5574                              <1> 	; 'sysgetgid' returns the real group ID of the current process.
  5575                              <1> 	; The real group ID identifies the group of the person
  5576                              <1> 	; who is logged in, in contradistinction to the effective
  5577                              <1> 	; group ID, which determines his access permission at each moment.
  5578                              <1> 	; It is thus useful to programs which operate using
  5579                              <1> 	; the 'set group ID' mode, to find out the group of the user
  5580                              <1> 	; who invoked them.
  5581                              <1> 
  5582                              <1> 	;movzx	eax, word [u.ruid]
  5583                              <1> 	; 09/01/2022
  5584 00004E14 66A1[FC740000]      <1> 	mov	ax, [u.ruid]
  5585 00004E1A C1E008              <1> 	shl	eax, 8
  5586                              <1> 	; user ID in byte 1 and byte 2
  5587 00004E1D A0[FF740000]        <1> 	mov	al, [u.rgid] ; group ID in byte 0
  5588 00004E22 A3[A8740000]        <1> 	mov	[u.r0], eax
  5589 00004E27 E9C2ECFFFF          <1> 	jmp	sysret
  5590                              <1> 
  5591                              <1> sysver: ; get operating system version
  5592                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5593                              <1> 	; 18/06/2021 - Retro UNIX 386 v2
  5594                              <1> 
  5595                              <1> 	;VMAJOR equ 2 ; Retro UNIX 386 v2
  5596                              <1> 	;VMINOR equ 0 ; Retro UNIX 386 v2.0 (v2.0.0)
  5597                              <1> 	;CURRENT_VERSION equ (VMAJOR*256)+VMINOR
  5598                              <1> 
  5599                              <1> 	; 09/01/2022
  5600                              <1> 	VMAJOR equ 1 ; Retro UNIX 386 v1
  5601                              <1> 	VMINOR equ 2 ; Retro UNIX 386 v1.2 (v1.2.0)
  5602                              <1> 	CURRENT_VERSION equ (VMAJOR*256)+VMINOR 		  
  5603                              <1> 
  5604                              <1> 	; 29/04/2016 - TRDOS 386 v2.0
  5605                              <1> 	;mov	dword [u.r0], 200h ; AH = major version, AL = minor version 
  5606                              <1> 	; 18/06/2021
  5607 00004E2C C705[A8740000]0201- <1> 	mov	dword [u.r0], CURRENT_VERSION ;	(ah = 2, al = 0)
  5607 00004E34 0000                <1>
  5608 00004E36 E9B3ECFFFF          <1> 	jmp	sysret
  5609                              <1> 
  5610                              <1> anyi: 
  5611                              <1> 	; 09/01/2022
  5612                              <1> 	; 02/01/2022
  5613                              <1> 	; 01/01/2022
  5614                              <1> 	; 27/12/2021 (Retro UNIX 386 v1.2)
  5615                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  5616                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5617                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  5618                              <1> 	;
  5619                              <1> 	; 'anyi' is called if a file deleted while open.
  5620                              <1> 	; "anyi" checks to see if someone else has opened this file.
  5621                              <1> 	;
  5622                              <1> 	; INPUTS ->
  5623                              <1> 	;    r1 - contains an i-number
  5624                              <1> 	;    fsp - start of table containing open files
  5625                              <1> 	;
  5626                              <1> 	; OUTPUTS ->
  5627                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  5628                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  5629                              <1> 	;    if file not found - bit in i-node map is cleared
  5630                              <1> 	;    			 (i-node is freed)
  5631                              <1> 	;               all blocks related to i-node are freed
  5632                              <1> 	;	        all flags in i-node are cleared
  5633                              <1> 	; ((AX = R1)) input
  5634                              <1> 	;
  5635                              <1> 	;    (Retro UNIX Prototype: 02/12/2012, UNIXCOPY.ASM)
  5636                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  5637                              <1> 	;
  5638                              <1> 		; / r1 contains an i-number
  5639 00004E3B BB[44710000]        <1> 	mov	ebx, fsp
  5640                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  5641                              <1> anyi_1: ; 1:
  5642                              <1> 	;cmp	eax, [ebx] ; 09/01/2022 (32 bit inode number)
  5643 00004E40 663B03              <1> 	cmp	ax, [ebx]
  5644                              <1> 		; cmp r1,(r2) / do i-numbers match?
  5645 00004E43 7423                <1> 	je	short anyi_3
  5646                              <1> 		; beq 1f / yes, 1f
  5647                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5648                              <1> 	;neg	ax
  5649                              <1> 	;	; neg r1 / no complement r1
  5650                              <1> 	;cmp	ax, [ebx]
  5651                              <1> 	;	; cmp r1,(r2) / do they match now?
  5652                              <1> 	;je	short anyi_3
  5653                              <1> 		; beq 1f / yes, transfer
  5654                              <1> 		; / i-numbers do not match
  5655                              <1> anyi_0:
  5656                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5657                              <1> 	;add	ebx, fp.size ; runix v2 fsp table size is 16 bytes
  5658                              <1> 	; 01/01/2022
  5659 00004E45 83C310              <1> 	add	ebx, 16 ; runix v2 fsp table size is 16 bytes
  5660                              <1> 	;;add	ebx, 10 ; fsp table size is 10 bytes
  5661                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  5662                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  5663                              <1> 	; 22/11/2021
  5664                              <1> 	;cmp	ebx, fsp + (NFILES*fp.size) ; fsp+(NFILES*16)
  5665                              <1> 	; 02/01/2022
  5666 00004E48 81FB[64740000]      <1> 	cmp	ebx, fsp + (nfiles*16)
  5667                              <1> 	; 01/01/2022
  5668                              <1> 	;cmp	ebx, fsp + (NFILES*16) ; fsp+(NFILES*fp.size)
  5669                              <1> 	;;cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  5670                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  5671                              <1> 			; / are we at last entry in the table
  5672 00004E4E 72F0                <1> 	jb	short anyi_1
  5673                              <1> 		; blt 1b / no, check next entries i-number
  5674                              <1> 	; 27/12/2021
  5675                              <1> 	;;cmp	ax, 32768
  5676                              <1> 	;cmp	ah, 80h ; negative number check
  5677                              <1> 	;	; tst r1 / yes, no match
  5678                              <1> 	;	; bge .+4
  5679                              <1> 	;jb	short anyi_2
  5680                              <1> 	;neg	ax
  5681                              <1> 	;	; neg r1 / make i-number positive
  5682                              <1> ;anyi_2:	
  5683 00004E50 E89A080000          <1> 	call	imap
  5684                              <1> 		; jsr r0,imap / get address of allocation bit 
  5685                              <1> 			    ; / in the i-map in r2
  5686                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  5687                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  5688                              <1>  	; not	dx
  5689 00004E55 F6D2                <1> 	not 	dl ; 0 at calculated bit position, other bits are 1
  5690                              <1>         ;and	[ebx], dx
  5691 00004E57 2013                <1> 	and 	[ebx], dl 
  5692                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  5693 00004E59 E88F070000          <1> 	call	itrunc
  5694                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  5695 00004E5E 66C705[44700000]00- <1>  	mov 	word [i.flgs], 0
  5695 00004E66 00                  <1>
  5696                              <1> 		; clr i.flgs / clear all flags in the i-node
  5697 00004E67 C3                  <1> 	retn
  5698                              <1> 		; rts r0 / return
  5699                              <1> anyi_3: ; 1: / i-numbers match
  5700                              <1> 	; 09/01/2022
  5701 00004E68 F6430501            <1> 	test	byte [ebx+5], 1 ; open for writing flag
  5702 00004E6C 74D7                <1> 	jz	short anyi_0	
  5703                              <1> 
  5704                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5705 00004E6E 804B0580            <1> 	or	byte [ebx+5], 80h ; set deleted file flag (bit 7)
  5706                              <1> 	; 22/06/2015
  5707                              <1> 	;inc 	byte [ebx+9]
  5708                              <1> 		; incb 7(r2) / increment upper byte of the 4th word
  5709                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  5710 00004E72 C3                  <1> 	retn
  5711                              <1> 		; rts r0
  2074                                  %include 'u3.s'      ; 10/05/2015
  2075                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2076                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2077                              <1> ; ****************************************************************************
  2078                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2079                              <1> ; Last Modification: 24/12/2021
  2080                              <1> ; ----------------------------------------------------------------------------
  2081                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2082                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2083                              <1> ;
  2084                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2085                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2086                              <1> ; <Bell Laboratories (17/3/1972)>
  2087                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2088                              <1> ;
  2089                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2090                              <1> ;
  2091                              <1> ; ****************************************************************************
  2092                              <1> 
  2093                              <1> tswitch: ; Retro UNIX 386 v1
  2094                              <1> tswap:
  2095                              <1> 	; 01/09/2015
  2096                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2097                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2098                              <1> 	; time out swap, called when a user times out.
  2099                              <1> 	; the user is put on the low priority queue.
  2100                              <1> 	; This is done by making a link from the last user
  2101                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2102                              <1> 	; then he is swapped out.
  2103                              <1> 	;
  2104                              <1> 	; Retro UNIX 386 v1 modification ->
  2105                              <1> 	;       swap (software task switch) is performed by changing
  2106                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2107                              <1> 	;	as in Retro UNIX 8086 v1.
  2108                              <1> 	;
  2109                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2110                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2111                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2112                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2113                              <1> 	;	compatibles was using 1MB segmented memory 
  2114                              <1> 	;	in 8086/8088 times.
  2115                              <1> 	;
  2116                              <1> 	; INPUTS ->
  2117                              <1> 	;    u.uno - users process number
  2118                              <1> 	;    runq+4 - lowest priority queue
  2119                              <1> 	; OUTPUTS ->
  2120                              <1> 	;    r0 - users process number
  2121                              <1> 	;    r2 - lowest priority queue address
  2122                              <1> 	;
  2123                              <1> 	; ((AX = R0, BX = R2)) output
  2124                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2125                              <1> 	;
  2126 00004E73 A0[F9740000]        <1> 	mov 	al, [u.uno]
  2127                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2128                              <1> 		; mov  $runq+4,r2 
  2129                              <1> 			; / move lowest priority queue address to r2
  2130 00004E78 E8CD000000          <1>         call 	putlu
  2131                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2132                              <1> 		             ; / u.uno's user
  2133                              <1> 
  2134                              <1> switch: ; Retro UNIX 386 v1
  2135                              <1> swap:
  2136                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2137                              <1> 	; 02/09/2015
  2138                              <1> 	; 01/09/2015
  2139                              <1> 	; 31/08/2015
  2140                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2141                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2142                              <1> 	; 'swap' is routine that controls the swapping of processes
  2143                              <1> 	; in and out of core.
  2144                              <1> 	;
  2145                              <1> 	; Retro UNIX 386 v1 modification ->
  2146                              <1> 	;       swap (software task switch) is performed by changing
  2147                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2148                              <1> 	;	as in Retro UNIX 8086 v1.
  2149                              <1> 	;
  2150                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2151                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2152                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2153                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2154                              <1> 	;	compatibles was using 1MB segmented memory 
  2155                              <1> 	;	in 8086/8088 times.
  2156                              <1> 	;
  2157                              <1> 	; INPUTS ->
  2158                              <1> 	;    runq table - contains processes to run.
  2159                              <1> 	;    p.link - contains next process in line to be run.
  2160                              <1> 	;    u.uno - process number of process in core	
  2161                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2162                              <1> 	; OUTPUTS ->
  2163                              <1> 	;    (original unix v1 -> present process to its disk block)
  2164                              <1> 	;    (original unix v1 -> new process into core -> 
  2165                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2166                              <1> 	;	   for new process)
  2167                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2168                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2169                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2170                              <1> 	;	 for now, it will swap the process if there is not
  2171                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2172                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2173                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2174                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2175                              <1> 	;
  2176                              <1> 	;    u.pri -points to highest priority run Q.
  2177                              <1> 	;    r2 - points to the run queue.
  2178                              <1> 	;    r1 - contains new process number
  2179                              <1> 	;    r0 - points to place in routine or process that called
  2180                              <1> 	;	  swap all user parameters
  2181                              <1> 	;				
  2182                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2183                              <1> 	;
  2184                              <1> swap_0:
  2185                              <1> 		; mov $300,*$ps / processor priority = 6
  2186 00004E7D BE[98740000]        <1> 	mov	esi, runq
  2187                              <1> 		; mov $runq,r2 / r2 points to runq table
  2188                              <1> swap_1: ; 1: / search runq table for highest priority process
  2189 00004E82 668B06              <1> 	mov	ax, [esi]
  2190 00004E85 6621C0              <1> 	and 	ax, ax
  2191                              <1>        		; tst (r2)+ / are there any processes to run 
  2192                              <1> 			  ; / in this Q entry
  2193 00004E88 7507                <1> 	jnz	short swap_2
  2194                              <1>        		; bne 1f / yes, process 1f
  2195                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2196                              <1> 			       ; / to end of table
  2197                              <1> 		; bne 1b / if not at end, go back
  2198 00004E8A E8E0000000          <1> 	call	idle
  2199                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2200                              <1> 				       ; / all queues are empty
  2201 00004E8F EBF1                <1> 	jmp	short swap_1
  2202                              <1> 		; br swap
  2203                              <1> swap_2: ; 1:
  2204 00004E91 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2205                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2206                              <1>  		; mov r2,u.pri / set present user to this run queue
  2207                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2208 00004E94 38E0                <1> 	cmp	al, ah
  2209                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2210                              <1> 			      ; / in this Q to be run
  2211 00004E96 740A                <1> 	je	short swap_3
  2212                              <1>        		; beq 1f / yes
  2213                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2214                              <1> 	;movzx	ebx, al
  2215 00004E98 8AA3[E3700000]      <1> 	mov	ah, [ebx+p.link-1] 
  2216 00004E9E 8826                <1>        	mov	[esi], ah
  2217                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2218                              <1> 				       ; / in line into run queue
  2219 00004EA0 EB05                <1> 	jmp	short swap_4
  2220                              <1>        		; br 2f
  2221                              <1> swap_3: ; 1:
  2222                              <1> 	;xor	dx, dx
  2223                              <1> 	; 24/12/2021
  2224 00004EA2 31D2                <1> 	xor	edx, edx
  2225 00004EA4 668916              <1> 	mov	[esi], dx
  2226                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2227                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2228                              <1>       ; / in new process if required
  2229                              <1>        		; clr *$ps / clear processor status
  2230 00004EA7 8A25[F9740000]      <1> 	mov 	ah, [u.uno]
  2231 00004EAD 38C4                <1> 	cmp	ah, al
  2232                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2233                              <1> 			      ; / the process in core?
  2234 00004EAF 743B                <1>        	je	short swap_8
  2235                              <1>        		; beq 2f / yes, don't have to swap
  2236                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2237                              <1> 			   ; / (address in routine that called swap)
  2238                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2239                              <1> 	; 01/09/2015
  2240                              <1> 	;mov	[u.usp], esp
  2241                              <1>        		; mov sp,u.usp / save stack pointer
  2242                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2243                              <1> 			       ; / to the stack pointer
  2244 00004EB1 08E4                <1> 	or	ah, ah
  2245                              <1>        		; tstb u.uno / is the process # = 0
  2246 00004EB3 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2247                              <1> 		; beq 1f / yes, kill process by overwriting
  2248                              <1> 	; 02/09/2015
  2249 00004EB5 8925[A4740000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2250                              <1> 	;
  2251 00004EBB E834000000          <1> 	call	wswap
  2252                              <1> 		; jsr r0,wswap / write out core to disk
  2253                              <1> 	 ; 31/08/2015
  2254                              <1> 	;movzx	ebx, al ; New (running) process number
  2255 00004EC0 EB1C                <1> 	jmp 	short swap_7
  2256                              <1> swap_6:
  2257                              <1> 	; 31/08/2015
  2258                              <1> 	; Deallocate memory pages belong to the process
  2259                              <1> 	; which is being terminated
  2260                              <1> 	; 14/05/2015 ('sysexit')
  2261                              <1>  	; Deallocate memory pages of the process
  2262                              <1> 	; (Retro UNIX 386 v1 modification !)
  2263                              <1> 	;
  2264                              <1> 	; movzx ebx, al
  2265 00004EC2 53                  <1> 	push	ebx
  2266 00004EC3 A1[08750000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2267 00004EC8 8B1D[0C750000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2268 00004ECE E803E0FFFF          <1> 	call	deallocate_page_dir
  2269 00004ED3 A1[04750000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2270 00004ED8 E891E0FFFF          <1> 	call	deallocate_page
  2271 00004EDD 5B                  <1> 	pop	ebx
  2272                              <1> swap_7: ;1: 
  2273                              <1> 	; 02/09/2015
  2274                              <1> 	; 31/08/2015
  2275                              <1> 	; 14/05/2015
  2276 00004EDE C0E302              <1> 	shl	bl, 2 ; * 4 
  2277 00004EE1 8B83[00710000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2278                              <1> 	;cli
  2279 00004EE7 E831000000          <1> 	call	rswap
  2280                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2281                              <1> 		; jsr r0,rswap / read new process into core
  2282                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2283                              <1> 			      ; / to his program to its normal
  2284                              <1> 	; 01/09/2015
  2285                              <1> 	;mov	esp, [u.usp]	
  2286                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2287                              <1> 			     ; / new process stack
  2288                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2289                              <1> 			     ; / that just got swapped in, left off.,
  2290                              <1> 			     ; / i.e., transfer control to new process
  2291                              <1> 	;sti
  2292                              <1> swap_8: ;2:
  2293                              <1> 	; RETRO UNIX 8086 v1 modification !
  2294 00004EEC C605[F0740000]04    <1> 	mov	byte [u.quant], time_count 
  2295                              <1> 		; movb $30.,uquant / initialize process time quantum
  2296 00004EF3 C3                  <1> 	retn
  2297                              <1> 		; rts r0 / return
  2298                              <1> 
  2299                              <1> wswap:  ; < swap out, swap to disk >
  2300                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2301                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2302                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2303                              <1> 	; appropriate disk area.
  2304                              <1> 	;
  2305                              <1> 	; Retro UNIX 386 v1 modification ->
  2306                              <1> 	;       User (u) structure content and the user's register content
  2307                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2308                              <1> 	;	saving 'u' structure and user registers for task switching).
  2309                              <1> 	;	u.usp - points to kernel stack address which contains
  2310                              <1> 	;		user's registers while entering system call.  
  2311                              <1> 	;	u.sp  - points to kernel stack address 
  2312                              <1> 	;		to return from system call -for IRET-.
  2313                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2314                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2315                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2316                              <1> 	;
  2317                              <1> 	; Retro UNIX 8086 v1 modification ->
  2318                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2319                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2320                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2321                              <1> 	;	compatibles was using 1MB segmented memory 
  2322                              <1> 	;	in 8086/8088 times.
  2323                              <1> 	;
  2324                              <1> 	; INPUTS ->
  2325                              <1> 	;    u.break - points to end of program
  2326                              <1> 	;    u.usp - stack pointer at the moment of swap
  2327                              <1> 	;    core - beginning of process program		
  2328                              <1> 	;    ecore - end of core 	
  2329                              <1> 	;    user - start of user parameter area		
  2330                              <1> 	;    u.uno - user process number	
  2331                              <1> 	;    p.dska - holds block number of process	
  2332                              <1> 	; OUTPUTS ->
  2333                              <1> 	;    swp I/O queue
  2334                              <1> 	;    p.break - negative word count of process 
  2335                              <1> 	;    r1 - process disk address	
  2336                              <1> 	;    r2 - negative word count
  2337                              <1> 	;
  2338                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2339                              <1> 	;
  2340                              <1> 	; INPUTS ->
  2341                              <1> 	;    u.uno - process number (to be swapped out)
  2342                              <1> 	; OUTPUTS ->
  2343                              <1> 	;    none
  2344                              <1> 	;
  2345                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2346                              <1> 	;
  2347 00004EF4 8B3D[04750000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2348 00004EFA B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2349 00004EFF BE[A0740000]        <1> 	mov	esi, user ; active user (u) structure	
  2350 00004F04 F3A5                <1> 	rep	movsd
  2351                              <1> 	;
  2352 00004F06 8B35[A4740000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2353                              <1> 			     ;      points to user registers)
  2354 00004F0C 8B0D[A0740000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2355                              <1> 			     ; (for IRET)
  2356                              <1> 			     ; [u.sp] -> EIP (user)
  2357                              <1> 			     ; [u.sp+4]-> CS (user)
  2358                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2359                              <1> 			     ; [u.sp+12] -> ESP (user)
  2360                              <1> 			     ; [u.sp+16] -> SS (user)	
  2361 00004F12 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2362 00004F14 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2363                              <1> 			     ; (for IRET) 	
  2364 00004F17 C1E902              <1> 	shr	ecx, 2	     		
  2365 00004F1A F3A5                <1> 	rep	movsd
  2366 00004F1C C3                  <1> 	retn
  2367                              <1> 
  2368                              <1> 	; Original UNIX v1 'wswap' routine:
  2369                              <1> 	; wswap:
  2370                              <1> 		; mov *$30,u.emt / determines handling of emts
  2371                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2372                              <1> 				; / illegal instructions
  2373                              <1> 		; mov u.break,r2 / put process program break address in r2
  2374                              <1> 		; inc r2 / add 1 to it 
  2375                              <1> 		; bic $1,r2 / make it even
  2376                              <1> 		; mov r2,u.break / set break to an even location
  2377                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2378                              <1> 			     ; / at moment of swap in r3
  2379                              <1> 		; cmp r2,$core / is u.break less than $core
  2380                              <1> 		; blos 2f / yes
  2381                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2382                              <1>        		; bhis 2f / yes
  2383                              <1> 	; 1:
  2384                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2385                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2386                              <1> 		; bne 1b / no, keep packing
  2387                              <1> 	 	; br 1f / yes
  2388                              <1> 	; 2:
  2389                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2390                              <1> 	; 1:
  2391                              <1>        		; sub $user,r2 / get number of bytes to write out 
  2392                              <1> 			   ; / (user up to end of stack gets written out)
  2393                              <1> 		; neg r2 / make it negative
  2394                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2395                              <1> 		; mov r2,swp+4 / word count
  2396                              <1> 		; movb u.uno,r1 / move user process number to r1
  2397                              <1> 		; asl r1 / x2 for index
  2398                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2399                              <1> 				     ; / into the p.break table
  2400                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2401                              <1> 				    ; /	for process to r1
  2402                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2403                              <1> 			     ; / (block number)
  2404                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2405                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2406                              <1> 	; 1:
  2407                              <1>        		; tstb swp+1 / is lt done writing?
  2408                              <1>        		; bne 1b / no, wait
  2409                              <1> 		; rts r0 / yes, return to swap
  2410                              <1> 
  2411                              <1> rswap:  ; < swap in, swap from disk >
  2412                              <1> 	; 15/09/2015
  2413                              <1> 	; 28/08/2015
  2414                              <1> 	; 14/05/2015
  2415                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2416                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2417                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2418                              <1> 	; from disk into core.
  2419                              <1> 	;
  2420                              <1> 	; Retro UNIX 386 v1 modification ->
  2421                              <1> 	;       User (u) structure content and the user's register content
  2422                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2423                              <1> 	;	saving 'u' structure and user registers for task switching).
  2424                              <1> 	;	u.usp - points to kernel stack address which contains
  2425                              <1> 	;		user's registers while entering system call.  
  2426                              <1> 	;	u.sp  - points to kernel stack address 
  2427                              <1> 	;		to return from system call -for IRET-.
  2428                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2429                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2430                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2431                              <1> 	;
  2432                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2433                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2434                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2435                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2436                              <1> 	;	compatibles was using 1MB segmented memory 
  2437                              <1> 	;	in 8086/8088 times.
  2438                              <1> 	;
  2439                              <1> 	; INPUTS ->
  2440                              <1> 	;    r1 - process number of process to be read in
  2441                              <1> 	;    p.break - negative of word count of process 
  2442                              <1> 	;    p.dska - disk address of the process		
  2443                              <1> 	;    u.emt - determines handling of emt's 	
  2444                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2445                              <1> 	; OUTPUTS ->
  2446                              <1> 	;    8 = (u.ilgins)
  2447                              <1> 	;    24 = (u.emt)
  2448                              <1> 	;    swp - bit 10 is set to indicate read 
  2449                              <1> 	;		(bit 15=0 when reading is done)	
  2450                              <1> 	;    swp+2 - disk block address
  2451                              <1> 	;    swp+4 - negative word count 	
  2452                              <1> 	;      ((swp+6 - address of user structure)) 
  2453                              <1> 	;
  2454                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2455                              <1> 	;
  2456                              <1> 	; INPUTS ->
  2457                              <1> 	;    AL	- new process number (to be swapped in)	 
  2458                              <1> 	; OUTPUTS ->
  2459                              <1> 	;    none
  2460                              <1> 	;
  2461                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2462                              <1> 	;
  2463                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2464 00004F1D 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2465 00004F1F B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2466 00004F24 BF[A0740000]        <1> 	mov	edi, user ; active user (u) structure	
  2467 00004F29 F3A5                <1> 	rep	movsd
  2468 00004F2B 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2469 00004F2C 8B3D[A4740000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2470                              <1> 			     ;      points to user registers)
  2471 00004F32 8B0D[A0740000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2472                              <1> 			     ; (for IRET)
  2473                              <1> 			     ; [u.sp] -> EIP (user)
  2474                              <1> 			     ; [u.sp+4]-> CS (user)
  2475                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2476                              <1> 			     ; [u.sp+12] -> ESP (user)
  2477                              <1> 			     ; [u.sp+16] -> SS (user)		
  2478                              <1> 	; 28/08/2015
  2479 00004F38 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2480 00004F3A 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2481                              <1> 			     ; (for IRET) 	
  2482 00004F3D C1E902              <1> 	shr	ecx, 2	       		
  2483 00004F40 F3A5                <1> 	rep	movsd
  2484 00004F42 8B25[A4740000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2485 00004F48 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2486 00004F49 C3                  <1> 	retn
  2487                              <1> 
  2488                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2489                              <1> 	;rswap:
  2490                              <1>        		; asl r1 / process number x2 for index
  2491                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2492                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2493                              <1>        		; bis $2000,swp / read
  2494                              <1>        		; jsr r0,ppoke / read it in 
  2495                              <1> 	; 1:
  2496                              <1>        		; tstb swp+1 / done
  2497                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2498                              <1>        		; mov u.emt,*$30 / yes move these
  2499                              <1>        		; mov u.ilgins,*$10 / back
  2500                              <1>        		; rts r0 / return
  2501                              <1> 
  2502                              <1> 	;unpack: ; / move stack back to its normal place
  2503                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2504                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2505                              <1> 		; blos 2f / yes, return
  2506                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2507                              <1> 			     ; / before swapping
  2508                              <1> 		; bhis 2f / yes, return
  2509                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2510                              <1> 		; add r3,r2
  2511                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2512                              <1> 	; 1:
  2513                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2514                              <1> 		; cmp r2,u.break / in core
  2515                              <1> 		; bne 1b
  2516                              <1> 	; 2:
  2517                              <1>        		; rts r0
  2518                              <1> 
  2519                              <1> putlu: 
  2520                              <1> 	; 12/09/2015
  2521                              <1> 	; 02/09/2015
  2522                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2523                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2524                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2525                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2526                              <1> 	; the last process on the queue to process in r1 by putting
  2527                              <1> 	; the process number in r1 into the last process's link.
  2528                              <1> 	;
  2529                              <1> 	; INPUTS ->
  2530                              <1> 	;    r1 - user process number
  2531                              <1> 	;    r2 - points to lowest priority queue 
  2532                              <1> 	;    p.dska - disk address of the process		
  2533                              <1> 	;    u.emt - determines handling of emt's 	
  2534                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2535                              <1> 	; OUTPUTS ->
  2536                              <1> 	;    r3 - process number of last process on the queue upon
  2537                              <1> 	;	  entering putlu
  2538                              <1> 	;    p.link-1 + r3 - process number in r1
  2539                              <1> 	;    r2 - points to lowest priority queue
  2540                              <1> 	;
  2541                              <1> 	; ((Modified registers: EDX, EBX)) 
  2542                              <1> 	;
  2543                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2544                              <1> 
  2545                              <1> 	; eBX = r2
  2546                              <1> 	; eAX = r1 (AL=r1b)
  2547                              <1> 
  2548 00004F4A BB[98740000]        <1> 	mov	ebx, runq
  2549 00004F4F 0FB613              <1> 	movzx  	edx, byte [ebx]
  2550 00004F52 43                  <1> 	inc	ebx
  2551 00004F53 20D2                <1> 	and	dl, dl
  2552                              <1> 		; tstb (r2)+ / is queue empty?
  2553 00004F55 740A                <1>        	jz	short putlu_1
  2554                              <1> 		; beq 1f / yes, branch
  2555 00004F57 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2556                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2557                              <1> 			     ; / in r3
  2558 00004F59 8882[E3700000]      <1>        	mov	[edx+p.link-1], al
  2559                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2560                              <1> 			     ; / "last users" link
  2561 00004F5F EB03                <1> 	jmp	short putlu_2
  2562                              <1> 		; br 2f /
  2563                              <1> putlu_1: ; 1:
  2564 00004F61 8843FF              <1> 	mov	[ebx-1], al
  2565                              <1>        		; movb r1,-1(r2) / user is only user; 
  2566                              <1> 			    ; / put process no. at beginning and at end
  2567                              <1> putlu_2: ; 2: 
  2568 00004F64 8803                <1> 	mov	[ebx], al
  2569                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2570                              <1> 			     ; / on the queue
  2571 00004F66 88C2                <1> 	mov	dl, al
  2572 00004F68 88B2[E3700000]      <1>         mov     [edx+p.link-1], dh ; 0
  2573                              <1> 		; dec r2 / restore r2
  2574 00004F6E C3                  <1>         retn
  2575                              <1> 		; rts r0
  2576                              <1> 
  2577                              <1> ;copyz:
  2578                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2579                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2580                              <1> ;       mov     (r0)+,r1
  2581                              <1> ;       mov     (r0)+,r2
  2582                              <1> ;1:
  2583                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2584                              <1> ;       cmp     r1,r2 
  2585                              <1> ;       blo     1b
  2586                              <1> ;       mov     (sp)+,r2 / restore r2
  2587                              <1> ;       mov     (sp)+,r1 / restore r1
  2588                              <1> ;       rts     r0 
  2589                              <1> 
  2590                              <1> idle:
  2591                              <1> 	; 01/09/2015
  2592                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2593                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2594                              <1> 	; (idle & wait loop)
  2595                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2596                              <1> 	; idle procedure!
  2597                              <1>       	;
  2598                              <1>   	; 01/09/2015
  2599 00004F6F FB                  <1> 	sti
  2600                              <1>       	; 29/07/2013
  2601 00004F70 F4                  <1>       	hlt
  2602 00004F71 90                  <1>       	nop ; 10/10/2013
  2603 00004F72 90                  <1>       	nop
  2604 00004F73 90                  <1>       	nop
  2605                              <1>       	; 23/10/2013
  2606 00004F74 90                  <1>       	nop
  2607 00004F75 90                  <1>       	nop
  2608 00004F76 90                  <1>       	nop
  2609 00004F77 90                  <1>       	nop
  2610 00004F78 C3                  <1>       	retn      
  2611                              <1> 
  2612                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2613                              <1> 	;clr *$ps / clear ps
  2614                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2615                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2616                              <1> 	;1 / wait for interrupt
  2617                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2618                              <1> 	;mov (sp)+,*$ps
  2619                              <1> 	;rts r0
  2620                              <1> 
  2621                              <1> clear:
  2622                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2623                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2624                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2625                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2626                              <1> 	; on the current device (cdev)
  2627                              <1> 	;	
  2628                              <1> 	; INPUTS ->
  2629                              <1> 	;    r1 - block number of block to be zeroed
  2630                              <1> 	;    cdev - current device number 
  2631                              <1> 	; OUTPUTS ->
  2632                              <1> 	;    a zeroed I/O buffer onto the current device
  2633                              <1> 	;    r1 - points to last entry in the I/O buffer
  2634                              <1> 	;
  2635                              <1> 	; ((AX = R1)) input/output
  2636                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2637                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2638                              <1> 
  2639 00004F79 E8FD110000          <1> 	call 	wslot
  2640                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2641                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2642 00004F7E 89DF                <1> 	mov	edi, ebx ; r5
  2643 00004F80 89C2                <1> 	mov	edx, eax
  2644 00004F82 B980000000          <1> 	mov	ecx, 128
  2645                              <1> 		; mov $256.,r3
  2646 00004F87 31C0                <1> 	xor	eax, eax
  2647 00004F89 F3AB                <1> 	rep	stosd
  2648 00004F8B 89D0                <1> 	mov	eax, edx
  2649                              <1> ; 1: 
  2650                              <1>        		; clr (r5)+ / zero data word in buffer
  2651                              <1>        		; dec r3
  2652                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2653                              <1> 	;call	dskwr
  2654                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2655                              <1>                              ; / block specified in r1
  2656                              <1> 	; eAX (r1) = block number
  2657                              <1> 	;retn
  2658                              <1> 		; rts r0
  2659                              <1> 	; 24/12/2021
  2660 00004F8D E905120000          <1> 	jmp	dskwr
  2075                                  %include 'u4.s'      ; 15/04/2015
  2076                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2077                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2078                              <1> ; ****************************************************************************
  2079                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2080                              <1> ; Last Modification: 05/12/2021
  2081                              <1> ; ----------------------------------------------------------------------------
  2082                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2083                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2084                              <1> ;
  2085                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2086                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2087                              <1> ; <Bell Laboratories (17/3/1972)>
  2088                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2089                              <1> ;
  2090                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2091                              <1> ;
  2092                              <1> ; ****************************************************************************
  2093                              <1> 
  2094                              <1> ;setisp:
  2095                              <1>        ;mov     r1,-(sp)
  2096                              <1>        ;mov     r2,-(sp)
  2097                              <1>        ;mov     r3,-(sp)
  2098                              <1>        ;mov     clockp,-(sp)
  2099                              <1>        ;mov     $s.syst+2,clockp
  2100                              <1>        ;jmp     (r0)
  2101                              <1> 
  2102                              <1> clock: ; / interrupt from 60 cycle clock
  2103                              <1> 	
  2104                              <1> 	; 14/10/2015
  2105                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2106                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2107                              <1> 
  2108                              <1>        ;mov     r0,-(sp) / save r0
  2109                              <1>        ;tst     *$lks / restart clock?
  2110                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2111                              <1>        ;inc     (r0)
  2112                              <1>        ;bne     1f
  2113                              <1>        ;inc     -(r0)
  2114                              <1> ;1:
  2115                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2116                              <1>        ;inc     (r0)
  2117                              <1>        ;bne     1f
  2118                              <1>        ;inc     -(r0)
  2119                              <1> ;1:
  2120                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2121                              <1> 
  2122 00004F92 803D[F0740000]00    <1> 	cmp	byte [u.quant], 0
  2123 00004F99 772C                <1> 	ja	short clk_1
  2124                              <1> 	;
  2125 00004F9B 803D[9E740000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2126 00004FA2 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2127 00004FA4 803D[F9740000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2128 00004FAB 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2129 00004FAD 66833D[F4740000]00  <1> 	cmp	word [u.intr], 0
  2130 00004FB5 7616                <1> 	jna	short clk_2
  2131                              <1> clk_0:
  2132                              <1> 	; 14/10/2015
  2133 00004FB7 FE05[9E740000]      <1> 	inc	byte [sysflg] ; Now, we are in system space
  2134 00004FBD 58                  <1> 	pop	eax ; return address to the timer interrupt
  2135                              <1> 	;
  2136 00004FBE B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2137                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2138 00004FC0 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2139                              <1> 	;
  2140 00004FC2 E98CEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2141                              <1> clk_1:
  2142 00004FC7 FE0D[F0740000]      <1> 	dec	byte [u.quant]
  2143                              <1> clk_2:
  2144 00004FCD C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2145                              <1> 
  2146                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2147                              <1> 
  2148                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2149                              <1>        ;decb    (r0)
  2150                              <1>        ;bge     1f / if less than 0
  2151                              <1>        ;clrb    (r0) / make it 0
  2152                              <1> ;1: / decrement time out counts return now if priority was not 0
  2153                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2154                              <1>        ;bge     2f / yes, check time outs
  2155                              <1>        ;tstb    (r0) / no, user timed out?
  2156                              <1>        ;bne     1f / no
  2157                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2158                              <1>        ;bne     1f / no, 1f
  2159                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2160                              <1>        ;sys     0 / sysrele
  2161                              <1>        ;rti
  2162                              <1> ;2: / priority is high so just decrement time out counts
  2163                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2164                              <1> ;2:
  2165                              <1>        ;tstb    (r0) / is the time out?
  2166                              <1>        ;beq     3f / yes, 3f (get next entry)
  2167                              <1>        ;decb    (r0) / no, decrement the time
  2168                              <1>        ;bne     3f / isit zero now?
  2169                              <1>        ;incb    (r0) / yes, increment the time
  2170                              <1> ;3:
  2171                              <1>        ;inc     r0 / next entry
  2172                              <1>        ;cmp     r0,$touts / end of toutt table?
  2173                              <1>        ;blo     2b / no, check this entry
  2174                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2175                              <1>        ;rti / return from interrupt
  2176                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2177                              <1>        ;mov     (sp)+,r0 / restore r0
  2178                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2179                              <1>        ;jsr     r0,setisp / save registers
  2180                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2181                              <1>                                ;  / the table
  2182                              <1> ;1:
  2183                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2184                              <1>        ;beq     2f / yes
  2185                              <1>        ;decb    toutt(r0) / no, decrement the time
  2186                              <1>        ;bne     2f / is the time 0, now
  2187                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2188                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2189                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2190                              <1> ;2:
  2191                              <1>        ;dec     r0 / set up r0 for next entry
  2192                              <1>        ;bge     1b / finished? , no, go back
  2193                              <1>        ;br      retisp / yes, restore registers and do a rti
  2194                              <1> 
  2195                              <1> ;retisp:
  2196                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2197                              <1>        ;mov     (sp)+,r3
  2198                              <1>        ;mov     (sp)+,r2
  2199                              <1>        ;mov     (sp)+,r1
  2200                              <1>        ;mov     (sp)+,r0
  2201                              <1>        ;rti     / return from interrupt
  2202                              <1> 
  2203                              <1> 
  2204                              <1> wakeup: ; / wakeup processes waiting for an event 
  2205                              <1> 	; / by linking them to the queue
  2206                              <1> 	;
  2207                              <1> 	; 15/09/2015
  2208                              <1> 	; 29/06/2015
  2209                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2210                              <1> 	;
  2211                              <1> 	; 15/05/2013 - 02/06/2014
  2212                              <1> 	; Retro UNIX 8086 v1 modification !
  2213                              <1> 	; (Process/task switching routine by using
  2214                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2215                              <1> 	;
  2216                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2217                              <1> 	; sleeping in the specified wait channel by creating a link 
  2218                              <1> 	; to it from the last user process on the run queue.
  2219                              <1> 	; If there is no process to wake up, nothing happens.
  2220                              <1> 	;
  2221                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2222                              <1> 	; 'switching' status of the current process (owns current tty)
  2223                              <1> 	; (via alt + function keys) to a process which has highest
  2224                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2225                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2226                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2227                              <1> 	; tty for tty switching by keyboard.)	 
  2228                              <1> 	; 
  2229                              <1> 	; INPUT -> 
  2230                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2231                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2232                              <1> 	;
  2233                              <1> 	; ((modified registers: EAX, EBX))
  2234                              <1> 	;
  2235 00004FCE 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2236 00004FD1 81C3[E86F0000]      <1> 	add	ebx, wlist
  2237 00004FD7 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2238 00004FD9 20C0                <1> 	and	al, al
  2239 00004FDB 7424                <1> 	jz	short wa0 ; nothing to wakeup
  2240                              <1> 	;
  2241 00004FDD 30E4                <1> 	xor	ah, ah
  2242 00004FDF 8825[F0740000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2243 00004FE5 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2244                              <1> 	; 15/09/2015
  2245 00004FE7 0FB6D8              <1> 	movzx	ebx, al
  2246 00004FEA 88A3[D3700000]      <1> 	mov	[ebx+p.waitc-1], ah ; 0
  2247 00004FF0 FEC4                <1> 	inc	ah
  2248 00004FF2 88A3[F3700000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2249                              <1> 	;
  2250 00004FF8 57                  <1> 	push	edi
  2251 00004FF9 52                  <1> 	push	edx
  2252 00004FFA E84BFFFFFF          <1> 	call	putlu
  2253 00004FFF 5A                  <1> 	pop	edx
  2254 00005000 5F                  <1> 	pop	edi
  2255                              <1> wa0:
  2256 00005001 C3                  <1> 	retn
  2257                              <1> 
  2258                              <1> 	; 05/12/2021
  2259                              <1> 	; 30/11/2021 - Retro UNIX 386 v1.2
  2260                              <1> sleep: 
  2261                              <1> 	; 15/09/2015
  2262                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2263                              <1> 	;
  2264                              <1> 	; 09/05/2013 - 20/03/2014
  2265                              <1> 	;
  2266                              <1> 	; Retro UNIX 8086 v1 modification !
  2267                              <1> 	; (Process/task switching and quit routine by using
  2268                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2269                              <1> 	;
  2270                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2271                              <1> 	; tty and tape output or input becomes available
  2272                              <1> 	; and process is put on waiting channel and swapped out,
  2273                              <1> 	; then -when the tty or tape is ready to write or read-
  2274                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2275                              <1> 	;
  2276                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2277                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2278                              <1> 	; status of the current process also INT 1Ch will count down
  2279                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2280                              <1> 	; to tty buffer of the current process and kernel will get
  2281                              <1> 	; user input by using tty buffer of the current process
  2282                              <1> 	; (instead of standard INT 16h interrupt).
  2283                              <1> 	; TTY output will be redirected to related video page of text mode
  2284                              <1> 	; (INT 10h will be called with different video page depending
  2285                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2286                              <1> 	; pseudo screens.)
  2287                              <1> 	;
  2288                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2289                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2290                              <1> 	; characters/data on serial port(s).
  2291                              <1> 	;
  2292                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2293                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2294                              <1> 	; 
  2295                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2296                              <1> 	;
  2297                              <1> 	;; 05/10/2013
  2298                              <1>         ;10/12/2013
  2299                              <1> 	;cmp   byte [u.uno], 1
  2300                              <1>         ;ja    short sleep0
  2301                              <1> 	;retn
  2302                              <1> 
  2303                              <1> 	; 20/03/2014
  2304                              <1> 	;mov	bx, [runq]
  2305                              <1> 	;cmp	bl, bh
  2306                              <1> 	;jne	short sleep0	
  2307                              <1> 	; 25/02/2014
  2308                              <1> 	;cmp	word ptr [runq], 0
  2309                              <1> 	;ja	short sleep0	
  2310                              <1> 	;retn
  2311                              <1> sleep0:
  2312                              <1> 	;
  2313 00005002 E851000000          <1> 	call	isintr
  2314                              <1> 	;jnz	sysret
  2315                              <1> 		; / wait for event
  2316                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2317                              <1> 			      ; / or quit from user
  2318                              <1>                		; br 2f / something happened
  2319                              <1> 			      ; / yes, his interrupt so return
  2320                              <1>                      	      ;	/ to user
  2321                              <1> 	; 05/12/2021
  2322 00005007 7405                <1> 	jz	short sleep_2
  2323                              <1> sleep_3:
  2324 00005009 E9E0EAFFFF          <1> 	jmp	sysret
  2325                              <1> sleep_2:
  2326                              <1> 	; 30/06/2015
  2327 0000500E 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2328 00005011 81C3[E86F0000]      <1> 	add	ebx, wlist
  2329 00005017 8A03                <1> 	mov	al, [ebx]
  2330 00005019 20C0                <1> 	and	al, al
  2331 0000501B 7407                <1> 	jz	short sleep1
  2332 0000501D 53                  <1> 	push	ebx
  2333 0000501E E827FFFFFF          <1> 	call	putlu
  2334 00005023 5B                  <1> 	pop	ebx
  2335                              <1> sleep1:
  2336 00005024 A0[F9740000]        <1> 	mov	al, [u.uno]    
  2337 00005029 8803                <1>   	mov	[ebx], al 	; put the process number
  2338                              <1> 				; in the wait channel
  2339                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2340                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2341                              <1> 				     ; / on the stack
  2342                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2343                              <1> 				     ; / to put to sleep in there
  2344                              <1> 	; 30/11/2021
  2345 0000502B 31DB                <1> 	xor	ebx, ebx
  2346 0000502D 8A1D[89740000]      <1> 	mov	bl, [cdev]
  2347 00005033 53                  <1> 	push	ebx
  2348                              <1>         ; 15/09/2015
  2349                              <1> 	;movzx	ebx, al
  2350 00005034 88C3                <1> 	mov	bl, al
  2351 00005036 C683[F3700000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2352 0000503D FEC4                <1> 	inc	ah
  2353 0000503F 88A3[D3700000]      <1> 	mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2354                              <1> 	;
  2355                              <1> 	;push	word [cdev]
  2356                              <1> 	;	; mov cdev,-(sp) / nothing happened in isintr so
  2357 00005045 E833FEFFFF          <1> 	call	swap
  2358                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2359                              <1>         ;pop	word [cdev]
  2360                              <1> 	;	; mov (sp)+,cdev / restore device
  2361                              <1> 	; 30/11/2021
  2362 0000504A 58                  <1> 	pop	eax
  2363 0000504B A2[89740000]        <1> 	mov	[cdev], al
  2364 00005050 E803000000          <1> 	call	isintr
  2365                              <1> 	; 22/09/2013
  2366                              <1> 	;jnz	sysret         
  2367                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2368                              <1>                		; br 2f / yes, return to new user
  2369                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2370                              <1> 				; / originally on the wait channel
  2371                              <1>        		; beq 1f / if 0 branch
  2372                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2373                              <1>        		; mov $300,*$ps / processor priority = 6
  2374                              <1> 		; jsr r0,putlu / create link to old process number
  2375                              <1>        		; clr *$ps / clear the status; process priority = 0
  2376                              <1> 	; 05/12/2021
  2377 00005055 75B2                <1> 	jnz	short sleep_3 ; jump to sysret
  2378                              <1>      ;1:
  2379 00005057 C3                  <1> 	retn
  2380                              <1> 		; rts r0 / return
  2381                              <1>      ;2:
  2382                              <1>         ;;jmp	sysret
  2383                              <1> 		; jmp sysret / return to user
  2384                              <1> 
  2385                              <1> isintr:
  2386                              <1> 	; 30/11/2021	
  2387                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2388                              <1> 	;
  2389                              <1> 	; 09/05/2013 - 30/05/2014
  2390                              <1> 	;
  2391                              <1> 	; Retro UNIX 8086 v1 modification !
  2392                              <1> 	; (Process/task switching and quit routine by using
  2393                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2394                              <1> 	;
  2395                              <1> 	; Retro UNIX 8086 v1 modification:
  2396                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2397                              <1> 	;  and there is a 'quit' request by user;
  2398                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2399                              <1> 	;  "nothing to do". (20/10/2013)
  2400                              <1> 	;
  2401                              <1> 	; 20/10/2013
  2402 00005058 66833D[DE740000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2403 00005060 761F                <1> 	jna	short isintr2 ; retn
  2404                              <1> 	; 03/09/2013
  2405                              <1> 	; (nothing to do)
  2406                              <1> 	;retn
  2407                              <1> 	; 22/09/2013
  2408 00005062 66833D[F4740000]00  <1> 	cmp	word [u.intr], 0
  2409 0000506A 7615                <1> 	jna	short isintr2 ; retn
  2410                              <1> 	; 30/05/2014
  2411                              <1> 	;push	ax
  2412 0000506C 50                  <1> 	push	eax ; 30/11/2021 
  2413 0000506D 66A1[F6740000]      <1> 	mov	ax, [u.quit]
  2414 00005073 6609C0              <1> 	or	ax, ax ; 0 ?
  2415 00005076 7408                <1> 	jz	short isintr1 ; zf = 1
  2416 00005078 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2417 0000507C 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2418                              <1> 	;xor	ax, ax ; zf = 1
  2419                              <1> 	; 30/11/2021
  2420 0000507E 31C0                <1> 	xor	eax, eax
  2421                              <1> isintr1:
  2422                              <1> 	;pop	ax
  2423                              <1> 	; 30/11/2021
  2424 00005080 58                  <1> 	pop	eax
  2425                              <1> isintr2: ; 22/09/2013
  2426                              <1> 	; zf=1 -> nothing to do
  2427 00005081 C3                  <1> 	retn
  2428                              <1> 
  2429                              <1> 	; UNIX v1 original 'isintr' routine... 
  2430                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2431                              <1>        	;mov     r2,-(sp) / save r2
  2432                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2433                              <1>         ;                 / typewriter
  2434                              <1>        	;beq     1f / if 0, do nothing except skip return
  2435                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2436                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2437                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2438                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2439                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2440                              <1>         ;              / of interrupts
  2441                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2442                              <1>      ;1:
  2443                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2444                              <1>      ;4:
  2445                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2446                              <1>        	;mov     (sp)+,r1
  2447                              <1>        	;rts     r0
  2448                              <1>      ;3: / interrupt char = quit (fs)
  2449                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2450                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2451                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2452                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2453                              <1>      ;1: / find process control tty entry in tty block
  2454                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2455                              <1>        	;beq     1f / block found go to 1f
  2456                              <1>        	;add     $8,r1 / look at next tty block
  2457                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2458                              <1>        	;blo     1b / no
  2459                              <1>        	;br      4b / no process control tty found so go to 4b
  2460                              <1>      ;1:
  2461                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2462                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2463                              <1>         ;                  / identifier
  2464                              <1>        	;inc     0f / increment
  2465                              <1>      ;1:
  2466                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2467                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2468                              <1>         ;             / being typed out after you hit the interrupt
  2469                              <1>         ;             / key
  2470                              <1>        	;br      1b
  2076                                  %include 'u5.s'      ; 03/06/2015
  2077                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2078                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2079                              <1> ; ****************************************************************************
  2080                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2081                              <1> ; Last Modification: 11/02/2022
  2082                              <1> ; ----------------------------------------------------------------------------
  2083                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2084                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2085                              <1> ;
  2086                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2087                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2088                              <1> ; <Bell Laboratories (17/3/1972)>
  2089                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2090                              <1> ;
  2091                              <1> ; Retro UNIX 8086 v1 - U5.AS M (07/08/2013) //// UNIX v1 -> u5.s
  2092                              <1> ;
  2093                              <1> ; ****************************************************************************
  2094                              <1> 
  2095                              <1> 	; 09/01/2022
  2096                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2097                              <1> mget_w:
  2098                              <1> 	; 28/10/2021
  2099                              <1> 	; 22/08/2021
  2100                              <1> 	; 20/08/2021
  2101                              <1> 	; 25/05/2020
  2102                              <1> 	; 24/05/2020 - Retro UNIX 386 v2	
  2103 00005082 C605[3E750000]01    <1> 	mov	byte [mget_rw], 1 ; write access
  2104 00005089 EB07                <1> 	jmp	short mget
  2105                              <1> mget_r:
  2106                              <1> 	; 28/10/2021
  2107                              <1> 	; 22/08/2021
  2108                              <1> 	; 25/05/2020
  2109                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2110 0000508B C605[3E750000]00    <1> 	mov	byte [mget_rw], 0 ; read access	
  2111                              <1> mget:
  2112                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2113                              <1> 	; 28/11/2021
  2114                              <1> 	; 22/11/2021
  2115                              <1> 	; 28/10/2021 - temporary (simplified code)
  2116                              <1> 	; 22/08/2021
  2117                              <1> 	; 20/08/2021
  2118                              <1> 	; 25/05/2020
  2119                              <1> 	; 24/05/2020
  2120                              <1> 	; 05/05/2020
  2121                              <1> 	; 02/05/2020, 03/05/2020
  2122                              <1> 	; 29/04/2020 - Retro UNIX 386 v2
  2123                              <1> 	; New inode model/format (Modified UNIX v7 inode model)
  2124                              <1> 	;	
  2125                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2126                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2127                              <1> 	;
  2128                              <1> 	; Get existing or (allocate) a new disk block for file
  2129                              <1> 	; 
  2130                              <1> 	; INPUTS ->
  2131                              <1> 	;    u.fofp (file offset pointer)
  2132                              <1> 	;    inode 
  2133                              <1> 	;    u.off (file offset)
  2134                              <1> 	; OUTPUTS ->
  2135                              <1> 	;    r1 (physical block number)
  2136                              <1> 	;    r2, r3, r5 (internal)
  2137                              <1> 	;
  2138                              <1> 	; ((AX = R1)) output
  2139                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2140                              <1> 	;
  2141                              <1> 	; Modified registers: eax, edx, ebx, ecx, esi, edi, ebp
  2142                              <1> 
  2143                              <1> 	; Retro UNIX 386 v2 'mget' procedure
  2144                              <1> 	; source code reference:
  2145                              <1> 	; 'mget' procedure in UNIXHDCP.ASM (25/01/2020) by Erdogan Tan
  2146                              <1> 
  2147                              <1> 	; Get sector/block address for current file pointer
  2148                              <1> 	; (If file pointer points to a number greater than current file
  2149                              <1> 	; size, a new -empty- sector/block will be created/written.)
  2150                              <1> 
  2151                              <1> 	; Note: 'mget' procedure will be used for only RUNIX v2 FS.
  2152                              <1> 	;	(installable file system drivers will not use 'mget')
  2153                              <1> 	;	 !!! 512 bytes per sector !!!  ; 02/05/2020
  2154                              <1> 
  2155                              <1> 	; ! 64 bit fofp ! but Retro UNIX 386 v2 kernel will use 32 bit
  2156                              <1> 	; file offset for regular files and directories.
  2157                              <1> 	; ('mget' procedure will be called for regular files & directories)
  2158                              <1> 
  2159                              <1> 	; 28/10/2021
  2160                              <1> 	; Note: 'mget' uses only current inode ([ii], 'inode:')
  2161                              <1> 	; (inode must be loaded at 'inode:' addr by 'iget' before 'mget')  
  2162                              <1> 
  2163                              <1> 		; mov *u.fofp,mq / file offset in mq
  2164                              <1> 		; clr ac / later to be high sig
  2165                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2166                              <1> 		; mov mq,r2
  2167                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2168                              <1> 		; bne 4f / branch for large file
  2169                              <1> 
  2170                              <1> 	; 09/01/2022
  2171                              <1> 	; Return: eax = physical block/sector number
  2172                              <1> mget_0:	
  2173 00005092 8B35[BC740000]      <1>         mov     esi, [u.fofp]
  2174 00005098 8B1E                <1> 	mov	ebx, [esi]
  2175                              <1>         ; ebx = file offset
  2176                              <1> 
  2177                              <1> 	; 20/08/2021
  2178 0000509A C1EB09              <1> 	shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2179                              <1> 
  2180 0000509D F605[45700000]10    <1> 	test	byte [i.flgs+1], 10h ; is this a large or small file addr?
  2181 000050A4 7405                <1> 	jz	short mget_1 ; small file addressing
  2182 000050A6 E986000000          <1> 	jmp	mget_5	; large file addressing
  2183                              <1> mget_1:
  2184                              <1> 	; If large file flag is clear -not set- RUNIX v2 FS inode
  2185                              <1> 	; will contain 10 direct disk block/sector dword pointers.
  2186                              <1> 
  2187                              <1> 	; 05/05/2020
  2188                              <1> 	;shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2189                              <1> 
  2190 000050AB 83FB0A              <1> 	cmp	ebx, 10	; block 10
  2191 000050AE 733A                <1> 	jnb	short mget_3 ; file offset >= 5120
  2192                              <1> 
  2193                              <1> 	; 05/05/2020
  2194                              <1> 	;cmp	ebx, 5120
  2195                              <1> 	;jnb	short mget_3 ; file offset >= 5120
  2196                              <1> 
  2197                              <1> 	;mov	bl, bh
  2198                              <1> 	;and	bl, 1Eh ; clear all bits but bits 1,2,3,4 ; 0,2,..,18
  2199                              <1> 	;	; max. value = 12h = 10010b = 18 (because ebx <= 5119) 
  2200                              <1> 	;shl	bl, 1	; * 2 ; max. value = 24h = 100100b = 36
  2201                              <1> 	;xor	bh, bh  ; clear bh
  2202                              <1> 		; RUNIX v2 (RUFS 2) file system bytes per sector value
  2203                              <1> 		; is always 512.
  2204                              <1> 		; ebx = 4*(ebx/512)  = 0 to 36
  2205                              <1> 
  2206                              <1> 	; 05/05/2020
  2207 000050B0 C0E302              <1> 	shl	bl, 2 ; * 4
  2208                              <1> 		 ; ebx = 0 to 36
  2209                              <1> 
  2210 000050B3 8B83[50700000]      <1> 	mov	eax, [ebx+i.dskp] ; disk sector addr ptr 0 to 9 for file
  2211                              <1> 	; 22/08/2021
  2212 000050B9 89DE                <1> 	mov	esi, ebx
  2213                              <1> 	;xor	ebx, ebx ; 0
  2214                              <1> 	; 09/01/2022
  2215 000050BB 30DB                <1> 	xor	bl, bl
  2216                              <1> 
  2217 000050BD 09C0                <1> 	or	eax, eax
  2218 000050BF 7512                <1> 	jnz	short mget_2 ; existing block/sector (logical)
  2219                              <1> 
  2220 000050C1 56                  <1> 	push	esi ; * ; 22/08/2021
  2221 000050C2 E877010000          <1> 	call	alloc_m ; 24/05/2020	
  2222                              <1> 	;call	alloc	; allocate a new sector/block for this file	
  2223                              <1> 			; eax = sector/block number
  2224                              <1> 			; ebx = buffer header address
  2225 000050C7 5E                  <1> 	pop	esi ; * ; 22/08/2021
  2226                              <1> 	; 28/11/2021
  2227                              <1> 	;jc	short mget_2 
  2228                              <1> 			; cf = 1 -> eax = 'no free block' error
  2229                              <1> 	; 22/08/2021
  2230 000050C8 8986[50700000]      <1> 	mov	[esi+i.dskp], eax  ; logical sector/block address
  2231                              <1> 
  2232                              <1> 	; 09/01/2022
  2233 000050CE E8D0040000          <1> 	call	setimod	; set inode modification flag
  2234                              <1> 			; and set modification time
  2235                              <1> 
  2236                              <1> 	; eax = logical sector/block number
  2237                              <1> 	; ([idev] = logical drive number)
  2238                              <1> 	; 28/10/2021
  2239                              <1> 	; [cdev] = logical drive number (0 or 1)
  2240                              <1> 	;	(0 = root fs, 1 = mounted fs)
  2241                              <1> mget_2:
  2242                              <1> 	; 09/01/2022
  2243                              <1> 	; eax = logical sector/block number
  2244 000050D3 F605[89740000]01    <1> 	test	byte [cdev], 1
  2245 000050DA 7507                <1> 	jnz	short mget_14
  2246                              <1> 	; convert to physical sector/block number
  2247 000050DC 0305[58750000]      <1> 	add	eax, [systm+SB.BootSectAddr]
  2248 000050E2 C3                  <1> 	retn
  2249                              <1> 	; 09/01/2022
  2250                              <1> mget_14:
  2251                              <1> 	; convert to physical sector/block number
  2252 000050E3 0305[60770000]      <1> 	add	eax, [mount+SB.BootSectAddr]
  2253 000050E9 C3                  <1> 	retn
  2254                              <1> 	
  2255                              <1> 		; rts r0
  2256                              <1> mget_3: ; 3: / adding on block which changes small file to a large file
  2257                              <1> 	; 22/11/2021
  2258 000050EA E84F010000          <1> 	call	alloc_m ; 24/05/2020
  2259                              <1> 	;call	alloc	; allocate a new sector/block for this file
  2260                              <1> 			; eax = sector/block number
  2261                              <1> 			; ebx = buffer header  ; 24/05/2020
  2262                              <1> 	; 28/11/2021
  2263                              <1> 	;jc	short mget_2 ; error code in eax
  2264                              <1> 
  2265                              <1> 	; 09/01/2022
  2266                              <1> 	; convert to physical block/sector number
  2267 000050EF 50                  <1> 	push	eax ; *!* ; logical sector/block number 
  2268 000050F0 E8DEFFFFFF          <1> 	call	mget_2
  2269                              <1> 
  2270                              <1>         ; EAX (r1) = Physical block (sector) number
  2271 000050F5 E881100000          <1> 	call 	wslot
  2272                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2273                              <1> 			     ; / first data word in buffer
  2274                              <1>         ; EAX (r1) = Physical block number
  2275                              <1> 	; 28/11/2021
  2276                              <1> 	; ebx = buffer (data) address
  2277                              <1> 	; 22/11/2021
  2278 000050FA 31C9                <1> 	xor	ecx, ecx
  2279 000050FC B10A                <1> 	mov 	cl, 10	; r3, transfer old physical block pointers
  2280                              <1> 			; into new indirect block area for the new
  2281                              <1> 			; large file		
  2282 000050FE 89DF                <1> 	mov 	edi, ebx ; r5
  2283 00005100 BE[50700000]        <1> 	mov	esi, i.dskp  ; current inode's direct disk addr ptrs
  2284 00005105 89C2                <1> 	mov	edx, eax
  2285 00005107 31C0                <1> 	xor	eax, eax
  2286                              <1> mget_4:
  2287 00005109 A5                  <1> 	movsd 	
  2288 0000510A 8946FC              <1> 	mov	[esi-4], eax ; 0
  2289 0000510D E2FA                <1> 	loop	mget_4
  2290                              <1> 
  2291                              <1> 	; 22/11/2021
  2292 0000510F B176                <1> 	mov 	cl, 128-10 ; clear rest of data buffer
  2293                              <1> ;mget_4: ; 1
  2294 00005111 F3AB                <1> 	rep 	stosd
  2295                              <1> 		; clr (r5)+
  2296                              <1> 		; dec r3
  2297                              <1> 		; bgt 1b
  2298 00005113 89D0                <1> 	mov	eax, edx
  2299                              <1>         ; EAX (r1) = Physical block number
  2300 00005115 E87D100000          <1> 	call	dskwr
  2301                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2302                              <1> 
  2303                              <1> 	;; EAX (r1) = Physical block number
  2304                              <1> 
  2305                              <1> 	; 09/01/2022        
  2306 0000511A 8F05[50700000]      <1> 	pop	dword [i.dskp] ; *!* ; logical sector/block number
  2307                              <1>  
  2308                              <1> 	; eax = logical disk sector/block number/addr ; 09/01/2022
  2309                              <1> 	;mov 	[i.dskp], eax ; 22/11/2021 
  2310                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2311                              <1> 
  2312 00005120 800D[45700000]10    <1> 	or	byte [i.flgs+1], 10000b ; 10h ; 16  ; large file flag
  2313                              <1> 		; bis $10000,i.flgs / set large file bit 
  2314                              <1> 				  ; / in i.flgs word of i-node
  2315 00005127 E877040000          <1> 	call	setimod
  2316                              <1> 		; jsr r0,setimod / set i-node modified flag
  2317                              <1> 
  2318 0000512C E961FFFFFF          <1> 	jmp	mget_0 ; 09/01/2022
  2319                              <1> 		; br mget
  2320                              <1> 
  2321                              <1> mget_5:  ; 4 ; large file
  2322                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2323                              <1> 	;
  2324                              <1> 	; Retro UNIX 386 v2 disk inode contains..
  2325                              <1> 	; (if large file flag is set)
  2326                              <1> 	; 8 indirect disk block/sector dword pointers
  2327                              <1> 	; +1 double indirect disk block/sector dword pointers
  2328                              <1> 	; +1 triple indirect disk block/sector dword pointers
  2329                              <1> 
  2330                              <1> 	; check indirect pointers limit (as file offset)
  2331                              <1> 	; 8*128 = 1024 blocks (or sectors) or 512 KB
  2332                              <1> 	; check dx (file offset hw) value
  2333                              <1> 	
  2334                              <1> 	; 03/05/2020
  2335                              <1> 	;cmp	ebx, 524288  ; is file offset >= 524288 ?
  2336                              <1> 	;jnb	short mget_6 ; yes, check double indirect limit
  2337                              <1> 
  2338                              <1> 	; 05/05/2020
  2339 00005131 81FB00040000        <1> 	cmp	ebx, 1024    ; block 1024 (byte 524288)	
  2340 00005137 7321                <1> 	jnb	short mget_6 ; check double indirect limit
  2341                              <1> 
  2342 00005139 C605[40750000]01    <1> 	mov	byte [level], 1 ; levels, 1 = indirect blocks
  2343                              <1> 
  2344                              <1> 	; 05/05/2020
  2345                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2346                              <1> 
  2347 00005140 88D9                <1> 	mov	cl, bl
  2348 00005142 80E17F              <1> 	and	cl, 127
  2349 00005145 880D[41750000]      <1> 	mov	[level+1], cl ; level 1, direct block ptr index (0 to 127)
  2350 0000514B 66C1EB07            <1> 	shr	bx, 7 ; bl = level 0, indirect block pointer index (0 to 7)
  2351                              <1> 	;mov	[level+2], bl
  2352                              <1> 
  2353 0000514F C0E302              <1> 	shl	bl, 2 ; * 4 to convert index number to offset
  2354                              <1> 
  2355                              <1> 	;mov	esi, i.dskp
  2356                              <1> 	;add	esi, ebx
  2357                              <1> 
  2358 00005152 8DB3[50700000]      <1> 	lea	esi, [ebx+i.dskp]
  2359                              <1> 
  2360 00005158 EB66                <1> 	jmp	short mget_8
  2361                              <1> 
  2362                              <1> mget_6:
  2363                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2364                              <1> 	; 03/05/2020
  2365                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2366                              <1> 	; check double indirect pointer limit (as file offset)
  2367                              <1> 	; (128*128)+1024 = 16384+1024 blocks or 8 MB + 512 KB
  2368                              <1> 	; check dx (file offset hw) value
  2369                              <1> 	
  2370                              <1> 	;cmp	ebx, 8912896 ; >= 17408 sectors (16384+1024) ?	
  2371                              <1> 	;jnb	short mget_7 ; yes, use triple indirect pointer (block)
  2372                              <1> 
  2373                              <1> 	; 05/05/2020
  2374 0000515A 81FB00440000        <1> 	cmp	ebx, 17408   ; block 17408 (byte 8912896)	
  2375 00005160 7329                <1> 	jnb	short mget_7 ; use triple indirect pointer (block)
  2376                              <1> 
  2377 00005162 C605[40750000]02    <1> 	mov	byte [level], 2  ; levels, 2 = double indirect blocks
  2378                              <1> 	
  2379                              <1> 	;sub	ebx, 524288 ; 1024 sectors
  2380                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2381                              <1> 			; (from sector 1024)
  2382                              <1> 	; 05/05/2020
  2383 00005169 81EB00040000        <1> 	sub	ebx, 1024 ; offset from sector 1024
  2384                              <1> 	
  2385 0000516F 88D9                <1> 	mov	cl, bl
  2386 00005171 80E17F              <1> 	and	cl, 127
  2387 00005174 880D[41750000]      <1> 	mov	[level+1], cl
  2388                              <1> 			; level 2, direct block ptr index (0 to 127)	
  2389 0000517A 66C1EB07            <1> 	shr	bx, 7
  2390 0000517E 881D[42750000]      <1> 	mov	[level+2], bl
  2391                              <1> 			; level 1, indirect block ptr index (0 to 127)
  2392                              <1> 
  2393 00005184 BE[70700000]        <1> 	mov	esi, i.dskp + 32 ; 8*4
  2394                              <1> 			; level 0, double indirect block pointer
  2395 00005189 EB35                <1> 	jmp	short mget_8
  2396                              <1> 
  2397                              <1> mget_7:
  2398                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2399                              <1> 	; 03/05/2020
  2400                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2401                              <1> 	; triple indirect pointer ; 8912896 to 1082654720 bytes
  2402                              <1> 	;mov	esi, i.dskp + 36 ; 9*4
  2403                              <1> 
  2404 0000518B C605[40750000]03    <1> 	mov	byte [level], 3  ; levels, 3 = triple indirect blocks
  2405                              <1> 
  2406                              <1> 	;sub	ebx, 8912896 ; 17408 sectors (16384+1024)
  2407                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2408                              <1> 			; (from sector 17408)
  2409                              <1> 	; 05/05/2020
  2410 00005192 81EB00440000        <1> 	sub	ebx, 17408 ; offset from sector 17408	
  2411                              <1> 
  2412 00005198 88D9                <1> 	mov	cl, bl
  2413 0000519A 80E17F              <1> 	and	cl, 127
  2414 0000519D 880D[41750000]      <1> 	mov	[level+1], cl  
  2415                              <1> 			; level 3, direct block ptr index (0 to 127)	
  2416 000051A3 C1EB07              <1> 	shr	ebx, 7	
  2417 000051A6 88D9                <1> 	mov	cl, bl
  2418 000051A8 80E17F              <1> 	and	cl, 127
  2419 000051AB 880D[42750000]      <1> 	mov	[level+2], cl
  2420                              <1> 			; level 2, indirect block ptr index (0 to 127)
  2421 000051B1 66C1EB07            <1> 	shr	bx, 7
  2422 000051B5 881D[43750000]      <1> 	mov	[level+3], bl
  2423                              <1> 			; level 1, double indir blk ptr index (0 to 127)
  2424                              <1> 
  2425 000051BB BE[74700000]        <1> 	mov	esi, i.dskp + 36 ; 9*4
  2426                              <1> 			; level 0, triple indirect block pointer
  2427                              <1> mget_8:
  2428                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2429 000051C0 8B06                <1> 	mov	eax, [esi]
  2430 000051C2 09C0                <1> 	or 	eax, eax ; R1
  2431 000051C4 751A                <1> 	jnz 	short mget_10 ; 2f
  2432                              <1> 		; bne 2f / if no indirect block exists
  2433 000051C6 56                  <1> 	push	esi	; * ; 24/05/2020
  2434                              <1> 
  2435 000051C7 E872000000          <1> 	call	alloc_m ; 24/05/2020
  2436                              <1> 	;call	alloc	; allocate a new block for this file	
  2437                              <1> 			; eax = block number
  2438                              <1> 			; ebx = buffer header address
  2439                              <1> 			; [pdn] = physical drive number ; 25/05/2020
  2440                              <1> 	;jc	mget_2	; cf -> 1 & eax = 0 -> no free block
  2441                              <1> 
  2442 000051CC 5E                  <1> 	pop	esi	; * ; 24/05/2020
  2443                              <1> 	;jc	short mget_9
  2444                              <1> 
  2445                              <1> 	; 09/01/2022
  2446                              <1> 	; eax = logical sector/block number
  2447                              <1> 
  2448 000051CD 8906                <1> 	mov	[esi], eax ; record sector/block address on i.dskp area
  2449                              <1> 
  2450 000051CF E8CF030000          <1> 	call 	setimod
  2451                              <1> 		; jsr r0,setimod / set i-node modified byte
  2452                              <1> 	; EAX = new block number (logical)
  2453                              <1> 
  2454                              <1> 	; 09/01/2022
  2455                              <1> 	; convert to physical block/sector number
  2456 000051D4 E8FAFEFFFF          <1> 	call	mget_2
  2457                              <1> 	;
  2458 000051D9 E89BFDFFFF          <1> 	call 	clear
  2459                              <1> 		; jsr r0,clear / clear new block
  2460                              <1> 	; 22/11/2021
  2461 000051DE EB0A                <1> 	jmp	short mget_11
  2462                              <1> ;mget_9:
  2463                              <1> ;	pop	edx ; *  ; 09/01/2022
  2464                              <1> ;	retn
  2465                              <1> mget_10: ;2
  2466                              <1> 	; 09/01/2022
  2467                              <1> 	; eax = logical sector/block number/address
  2468                              <1> 	; convert to physical sector/block number/address
  2469 000051E0 E8EEFEFFFF          <1> 	call	mget_2	
  2470                              <1> 	; 05/03/2013
  2471                              <1> 	; EAX = r1, physical block number (of indirect block)
  2472 000051E5 E81F0F0000          <1> 	call 	dskrd ; read indirect block
  2473                              <1> 		; jsr r0,dskrd / read in indirect block
  2474                              <1> 	;jc	short mget_9
  2475                              <1> mget_11:
  2476                              <1> 	; 22/11/2021
  2477                              <1> 	; eax = physical block/sector address
  2478                              <1> 	; ebx = buffer address
  2479                              <1> 
  2480 000051EA 89C2                <1> 	mov	edx, eax ; *  ; save physical sector number in edx
  2481                              <1> 
  2482 000051EC 0FB605[40750000]    <1> 	movzx	eax, byte [level]
  2483 000051F3 8A80[40750000]      <1> 	mov	al, [eax+level] ; get sector pointer offset
  2484 000051F9 C1E002              <1> 	shl	eax, 2 ; * 4 ; 09/01/2022
  2485                              <1> 	;shl	ax, 2 ; * 4
  2486                              <1> 
  2487 000051FC 01C3                <1> 	add	ebx, eax
  2488                              <1> 
  2489 000051FE 8B03                <1> 	mov 	eax, [ebx] ; put logical block no of block
  2490                              <1> 			   ; in file sought in R1 (EAX)
  2491                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2492                              <1> 	               	    ; / sought in r1
  2493                              <1> 
  2494 00005200 21C0                <1> 	and	eax, eax  ; if logical sector/block number is zero
  2495                              <1> 			  ; then we need a new block for file
  2496 00005202 740F                <1> 	jz	short mget_12
  2497                              <1> 
  2498 00005204 FE0D[40750000]      <1> 	dec	byte [level]
  2499 0000520A 75D4                <1> 	jnz	short mget_10
  2500                              <1> 
  2501 0000520C 29DB                <1> 	sub	ebx, ebx ; ebx = 0 ; existing sector
  2502                              <1> 
  2503                              <1> 	;retn
  2504                              <1> 	; 09/01/2022
  2505                              <1> 	; eax = logical block/sector number
  2506 0000520E E9C0FEFFFF          <1> 	jmp	mget_2
  2507                              <1> 
  2508                              <1> mget_12:
  2509                              <1> 	; 22/11/2021
  2510 00005213 52                  <1> 	push	edx ; *
  2511 00005214 53                  <1> 	push	ebx ; ** ; buffer data position
  2512 00005215 E824000000          <1> 	call	alloc_m
  2513                              <1> 	;call	alloc	 ; allocate a new block for this file	
  2514                              <1> 			 ; eax = block number (logical)
  2515                              <1> 			 ; ebx = buffer header address
  2516 0000521A 5E                  <1> 	pop	esi ; **
  2517                              <1> 	; 09/01/2022
  2518                              <1> 	;pop	edx ; *
  2519                              <1> 	;jc	short mget_9 ; cf -> 1 & eax = 0 -> no free block
  2520                              <1> 
  2521 0000521B 8906                <1> 	mov	[esi], eax ; record/save block number (logical)
  2522                              <1> 
  2523                              <1> 	; 22/11/2021
  2524 0000521D 870424              <1> 	xchg	eax, [esp] ; *
  2525                              <1> 
  2526                              <1> 	; eax (r1) = physical block number (of indirect block)
  2527 00005220 E8560F0000          <1> 	call 	wslot
  2528                              <1> 		; jsr r0,wslot
  2529                              <1>         ; eax (r1) = physical block number
  2530                              <1> 	; ebx (r5) = pointer to buffer (indirect block)
  2531 00005225 E86D0F0000          <1> 	call 	dskwr
  2532                              <1> 	; eax = r1 = physical block number (of indirect block)
  2533                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2534                              <1> 			     ; / back out on disk
  2535 0000522A 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2536                              <1> 		; mov (sp),r1 / restore block number of new block	
  2537                              <1> 
  2538                              <1> 	; 09/01/2022
  2539                              <1> 	; eax = logical sector/block number/address of new block
  2540                              <1> 	; convert to physical sector/block number/address
  2541 0000522B E8A3FEFFFF          <1> 	call	mget_2	
  2542                              <1> 
  2543 00005230 E844FDFFFF          <1> 	call 	clear
  2544                              <1> 		; jsr r0,clear / clear new block
  2545                              <1> 
  2546 00005235 FE0D[40750000]      <1> 	dec	byte [level]
  2547 0000523B 75AD                <1> 	jnz	short mget_11
  2548                              <1> 
  2549                              <1> 	; 09/01/2022
  2550                              <1> 	; eax = physical sector/block number/address of new block
  2551                              <1> 	
  2552                              <1> 	; 22/11/2021
  2553                              <1> 	; ebx = buffer address
  2554                              <1> mget_13: ; 2
  2555                              <1> 	; eax (r1) = Block number of new block
  2556 0000523D C3                  <1> 	retn
  2557                              <1> 		; rts r0
  2558                              <1> 
  2559                              <1> 	; 09/01/2022
  2560                              <1> 	; 26/11/2021
  2561                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2562                              <1> alloc_m:
  2563                              <1> 	; 27/11/2021
  2564                              <1> 	; 28/10/2021
  2565                              <1> 	; 07/05/2021
  2566                              <1> 	; 26/05/2020
  2567                              <1> 	; 25/05/2020
  2568                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2569                              <1> 	; 'alloc' call in 'mget'
  2570                              <1> 	;
  2571                              <1> 	; (('mget_r' will be returned with error))
  2572                              <1> 	; (('mget_w' will continue to 'alloc'))
  2573                              <1> 
  2574                              <1> 	; Note: 'sysread' will return with cf = 0, eax = 0
  2575                              <1> 	; if [fofp] >= file size (eax = 0 --> EOF)
  2576                              <1> 	; So, if we are here, that means [fofp] < file size
  2577                              <1> 	;     but disk address is 0. 
  2578                              <1> 	
  2579 0000523E 803D[3E750000]01    <1> 	cmp	byte [mget_rw], 1 ; write access ? (mget_w) 
  2580 00005245 730F                <1> 	jnb	short alloc ; yes (this is a call from 'mget_w')
  2581                              <1> 	; ((cf = 1))	
  2582                              <1> 	; no (this is a call from 'mget_r') !
  2583                              <1> 	;mov	eax, ERR_FILE_SIZE ; file size error (inode error!)
  2584                              <1> 		; [User may change this empty/invalid inode (disk) sector
  2585                              <1> 		; pointer with a new valid inode (disk) sector pointer 
  2586                              <1> 		; by writing new clear (zero) sector to same file position
  2587                              <1> 		; in order to correct file size -inode parm/content- error.
  2588                              <1> 		; It may be useful for recovering lost data if other sector
  2589                              <1> 		; pointers are not empty.]	
  2590                              <1> 	;retn
  2591                              <1> 	; 27/11/2021
  2592 00005247 C705[1C750000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE 
  2592 0000524F 0000                <1>
  2593                              <1> 			; file size error (inode error!)
  2594 00005251 E978E8FFFF          <1> 	jmp	error
  2595                              <1> alloc:
  2596                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2597                              <1> 	; 27/11/2021
  2598                              <1> 	; 26/11/2021 - Major modification for Runix v2 file system
  2599                              <1> 	;	(I have called this kernel version as v1.2, it is a
  2600                              <1> 	;	 debug/test version just before Retro UNIX 386 v2 kernel)
  2601                              <1> 	;	((there were running problems on new version, 
  2602                              <1> 	;	  so i am developing an intermediate version with minimum
  2603                              <1> 	;	  modification on v1.1 code which is successfuly running))
  2604                              <1> 	;	 ; /// Erdogan Tan - Istanbul, 26/11/2021 /// 
  2605                              <1> 	;	 
  2606                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2607                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2608                              <1> 	;
  2609                              <1> 	; get a free block and 
  2610                              <1> 	; set the corresponding bit in the free storage map
  2611                              <1> 	; 
  2612                              <1> 	; INPUTS ->
  2613                              <1> 	;    cdev (current device)
  2614                              <1> 	;    r2 
  2615                              <1> 	;    r3
  2616                              <1> 	; OUTPUTS ->
  2617                              <1> 	;    r1 (physical block number of block assigned)
  2618                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2619                              <1> 	;
  2620                              <1> 	; ((AX = R1)) output
  2621                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2622                              <1>         ;    ((Modified registers: edx, ecx)) 
  2623                              <1> 
  2624                              <1> 	; 26/11/2021
  2625                              <1> 	; INPUT:
  2626                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2627                              <1> 	; OUTPUT:
  2628                              <1> 	;	eax = disk block/sector number/address (physical)
  2629                              <1> 	;	(ebx = disk buffer address for sector/block in eax)
  2630                              <1> 	;
  2631                              <1> 	;    Note:	
  2632                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2633                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2634                              <1> 	;	modification flag will be set; but the superblock 
  2635                              <1> 	;	will not be written to it's disk in this 'alloc' procedure)
  2636                              <1> 	;
  2637                              <1> 	; Modified registers: eax, ebx, ecx, edx, esi, edi, ebp
  2638                              <1> 
  2639                              <1> 	; 09/01/2022
  2640                              <1> 	; Return: eax = logical block/sector number 
  2641                              <1> 
  2642                              <1> 	; 26/11/2021
  2643 00005256 BB[54750000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2644                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2645 0000525B F605[89740000]01    <1> 	test	byte [cdev], 1
  2646                              <1> 		; tst cdev
  2647 00005262 7405                <1> 	jz	short alloc_1
  2648                              <1> 		; beq 1f / drum is device
  2649 00005264 BB[5C770000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2650                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2651                              <1> 			      ; / free storage map
  2652                              <1> alloc_1: ; 1
  2653                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2654 00005269 F6436A01            <1> 	test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2655 0000526D 7507                <1> 	jnz	short alloc_2  ; 'read only file system' error
  2656                              <1> 	;
  2657 0000526F 8B4B38              <1> 	mov	ecx, [ebx+SB.FreeBlocks] ; count of free blocks/sectors
  2658 00005272 21C9                <1> 	and	ecx, ecx
  2659 00005274 750F                <1> 	jnz	short alloc_3
  2660                              <1> alloc_2:
  2661                              <1> 	; 'no free blocks on disk !' error
  2662 00005276 C705[1C750000]2100- <1> 	mov	dword [u.error], ERR_ALLOC
  2662 0000527E 0000                <1>
  2663 00005280 E949E8FFFF          <1> 	jmp	error
  2664                              <1> alloc_3:
  2665                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2666 00005285 31C0                <1> 	xor	eax, eax
  2667                              <1> 	; 23/07/2021
  2668 00005287 8B4B3C              <1> 	mov	ecx, [ebx+SB.FirstFreeBlk] ; 1st free sector number
  2669                              <1> 					 ; (as logical sector number)
  2670 0000528A 09C9                <1> 	or	ecx, ecx
  2671 0000528C 7415                <1> 	jz	short alloc_5 ; 0 = initial/reset value or 'not valid'
  2672 0000528E 41                  <1> 	inc	ecx ; 0FFFFFFFFh -> 0
  2673 0000528F 7412                <1> 	jz	short alloc_5 ; 'not valid' or 'not calculated'
  2674 00005291 49                  <1> 	dec	ecx ; restore first free block value
  2675 00005292 89C8                <1> 	mov	eax, ecx
  2676                              <1> 	; 1 allocation byte (in fbm) is for 8 sectors
  2677 00005294 C1E903              <1> 	shr	ecx, 3	; first free block number / 8
  2678 00005297 80E1FC              <1> 	and	cl, ~3	; dword alignment (to backward)
  2679                              <1> 	; 27/11/2021
  2680 0000529A 890D[40750000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm
  2681                              <1> alloc_4:
  2682 000052A0 C1E80C              <1> 	shr	eax, 12 ; 1 fbm sector for 4096 sectors
  2683                              <1> alloc_5:
  2684                              <1> 	; 26/11/2021
  2685 000052A3 53                  <1> 	push	ebx ; ** ; superblock buffer address 
  2686                              <1> 	; eax = fbm sector index
  2687 000052A4 A3[44750000]        <1> 	mov	[free_map_index], eax
  2688 000052A9 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2689                              <1> 			; free blocks map start sector addr
  2690                              <1> 	; 09/01/2022
  2691 000052AC 034304              <1> 	add	eax, [ebx+SB.BootSectAddr] 
  2692                              <1> 			; + Hidden Sectors
  2693                              <1> 	;
  2694                              <1> 	; eax = physical sector number
  2695 000052AF E8550E0000          <1> 	call	dskrd
  2696                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2697                              <1> 	; eax = physical sector number
  2698                              <1> 	; ebx = buffer data address
  2699                              <1> 	; 27/11/2021
  2700 000052B4 8B15[40750000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2701 000052BA A3[48750000]        <1> 	mov	[free_map_sector], eax ; physical sector number
  2702 000052BF B9FF010000          <1> 	mov	ecx, 511
  2703                              <1> 	;and	edx, 511
  2704 000052C4 21CA                <1> 	and 	edx, ecx ; fbm byte offset in fbm buffer
  2705 000052C6 41                  <1> 	inc	ecx ; 512
  2706 000052C7 01D9                <1> 	add	ecx, ebx
  2707 000052C9 01DA                <1> 	add	edx, ebx ; + buffer address
  2708 000052CB 5B                  <1> 	pop	ebx ; ** ; superblock buffer address 
  2709                              <1> 	;
  2710                              <1> 	; ebx = superblock buffer address
  2711                              <1> 	; edx = superblock buffer address + byte offset (dword aligned)
  2712                              <1> 	; ecx = superblock buffer address + 512
  2713                              <1> alloc_6:
  2714                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2715                              <1> 	;		for Retro UNIX 386 v1.2
  2716                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 code
  2717                              <1> 	; (dword scan) ((1 dword = 32 sectors, 1 byte = 8 sectors))
  2718                              <1> 	; ((Note: Logical drive size must be multiplies of 32 sectors))
  2719                              <1> 	; 19/05/2020
  2720                              <1> 	; edx = free blocks map byte address 
  2721 000052CC 0FBC02              <1> 	bsf	eax, [edx] ; Scans source operand for first bit set (1).
  2722                              <1> 			  ; Clear ZF if a bit is found set (1) and 
  2723                              <1> 			  ; loads the destination with an index to
  2724                              <1> 			  ; first set bit. (0 -> 31) 
  2725                              <1> 			  ; Sets ZF to 1 if no bits are found set.
  2726 000052CF 752A                <1> 	jnz	short alloc_8 ; ZF = 0 -> a free block has been found
  2727                              <1> 
  2728 000052D1 A1[40750000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2729 000052D6 83C004              <1> 	add	eax, 4 ; next dword
  2730 000052D9 3B431C              <1> 	cmp	eax, [ebx+SB.FreeMapSize] ; fbm size in bytes
  2731 000052DC 7209                <1> 	jb	short alloc_7
  2732                              <1> 	; invalidate superblock's first free block field
  2733 000052DE C7433CFFFFFFFF      <1> 	mov	dword [ebx+SB.FirstFreeBlk], 0FFFFFFFFh
  2734                              <1> 	; 'no free blocks on disk !' error
  2735 000052E5 EB8F                <1> 	jmp	alloc_2
  2736                              <1> alloc_7:
  2737                              <1> 		; 26/05/2020
  2738                              <1> 		; NOTE: If ldrv size is not multiplies of 32 sectors,
  2739                              <1> 		; mod (ldrv size / 32) sectors (at the end of ldrv)
  2740                              <1> 		; can not be allocated (for regular files or dirs)! 
  2741                              <1> 		; (Kernel or runix fs installation program can use
  2742                              <1> 		;  this fact to save/duplicate critical sectors/data 
  2743                              <1> 		;  onto end sectors of that logical drive's runix fs.)
  2744                              <1> 
  2745                              <1> 	; 26/11/2021
  2746 000052E7 A3[40750000]        <1> 	mov	[free_map_offset], eax
  2747                              <1> 	; 28/07/2021
  2748                              <1> 	; set next first free block value for search
  2749 000052EC C1E003              <1> 	shl	eax, 3 ; * 8 ; first free block
  2750                              <1>  	; 26/11/2021
  2751 000052EF 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2752                              <1> 	; search (scan) for next free block map dword (in buffer)
  2753 000052F2 83C204              <1> 	add	edx, 4 ; next dword
  2754 000052F5 39CA                <1> 	cmp	edx, ecx
  2755 000052F7 72D3                <1> 	jb	short alloc_6
  2756                              <1> 	; 27/11/2021
  2757 000052F9 EBA5                <1> 	jmp	short alloc_4
  2758                              <1> 
  2759                              <1> alloc_8:
  2760                              <1> 	; 26/11/2021
  2761                              <1> 	; convert bit index to xor value
  2762                              <1> 	; and then set allocated flag for corresponding fbm bit 
  2763 000052FB 89C1                <1> 	mov	ecx, eax
  2764                              <1> 	;mov	cl, al 
  2765                              <1> 	;sub	eax, eax
  2766                              <1> 	;inc	al ; eax = 1
  2767 000052FD B001                <1> 	mov	al, 1
  2768 000052FF D3E0                <1> 	shl	eax, cl
  2769 00005301 3102                <1> 	xor	[edx], eax  ; clear allocated block's bit in the fbm
  2770                              <1> 	; zero bit means allocated disk block (1 means free disk block) 
  2771                              <1> 
  2772 00005303 A1[40750000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2773                              <1> 		; note: eax is dword aligned (0,4,8,12..) !
  2774 00005308 C1E003              <1> 	shl	eax, 3 ; * 8 ; free block number base
  2775 0000530B 01C8                <1> 	add	eax, ecx ; add allocation bit index (0 to 31)	
  2776 0000530D 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax ; current free block
  2777                              <1> 				; (which is being allocated here)
  2778                              <1> 
  2779                              <1> 	;mov	eax, [ebx+SB.FreeMapAddr] 
  2780                              <1> 	;		; free blocks map start sector addr
  2781                              <1> 	;add	eax, [free_map_index]
  2782                              <1> 	
  2783                              <1> 	;;add	eax, [ebx+SB.BootSectAddr] 
  2784                              <1> 	;		; + Hidden Sectors
  2785                              <1> 	; eax = physical sector number
  2786                              <1> 	
  2787                              <1> 	; 27/11/2021
  2788 00005310 A1[48750000]        <1> 	mov	eax, [free_map_sector] ; physical sector number
  2789                              <1> 	
  2790 00005315 E8610E0000          <1> 	call	wslot
  2791                              <1> 	; ebx = buffer data address (write operation bit is set)
  2792                              <1> 	; eax = physical sector number
  2793                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2794                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2795                              <1> 
  2796                              <1> 	; 27/11/2021
  2797                              <1> 	;mov	[free_map_buffer], ebx ; save free map buffer address
  2798                              <1> 
  2799 0000531A E8780E0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2800                              <1> 		      ; (at the beginning/head of the buffer chain)
  2801                              <1> 
  2802                              <1> 	; if we are here, buffer has been written to disk successfully 
  2803                              <1> 	; (otherwise cpu would jump to 'error' address)
  2804                              <1> 
  2805                              <1> 	; set superblock modified flag
  2806 0000531F BA[9C740000]        <1> 	mov	edx, smod
  2807 00005324 BB[54750000]        <1> 	mov	ebx, systm
  2808 00005329 F605[89740000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2809 00005330 7406                <1> 	jz	short alloc_9  ; no, root device
  2810                              <1> 	; yes, mounted device
  2811 00005332 BB[5C770000]        <1> 	mov	ebx, mount
  2812                              <1> 	;mov	edx, mmod
  2813 00005337 42                  <1> 	inc	edx ; edx = offset mmod
  2814                              <1> alloc_9: 
  2815 00005338 FE02                <1> 	inc	byte [edx] ; superblock modified !
  2816                              <1> 	
  2817                              <1> 	; Allocating a new sector/block (for file) has been completed here.
  2818 0000533A 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2819 0000533D 40                  <1> 	inc	eax ; 0FFFFFFFFh -> 0 
  2820 0000533E 7405                <1> 	jz	short alloc_10 ; not valid (not set)
  2821 00005340 48                  <1> 	dec	eax ; Free Blocks
  2822 00005341 48                  <1> 	dec	eax ; Free Blocks = Free Blocks - 1
  2823 00005342 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax
  2824                              <1> alloc_10:
  2825 00005345 E8150F0000          <1> 	call	get_system_time
  2826                              <1> 		; eax = current time (as unix epoch time)
  2827                              <1> 	; 30/07/2021
  2828 0000534A 89435C              <1> 	mov	[ebx+SB.ModifTime], eax
  2829                              <1> 
  2830 0000534D 8B433C              <1> 	mov	eax, [ebx+SB.FirstFreeBlk] ; allocated block address
  2831 00005350 FF433C              <1> 	inc	dword [ebx+SB.FirstFreeBlk] 
  2832                              <1> 				; +1, new value of first free block
  2833                              <1> 				; (new search will be started from here)
  2834                              <1> 				; ((it may not be free, no problem))
  2835                              <1> 
  2836                              <1> 	; put free map buffer address in ebx
  2837                              <1> 	; 27/11/2021
  2838                              <1> 	;mov	ebx, [free_map_buffer]
  2839                              <1> 
  2840 00005353 C3                  <1> 	retn	
  2841                              <1> 
  2842                              <1> 	; 11/02/2022
  2843                              <1> 	; 09/01/2022
  2844                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2845                              <1> free:
  2846                              <1> 	; 11/02/2022
  2847                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2848                              <1> 	; 05/11/2021
  2849                              <1> 	; 29/10/2021 - temporary (simplified code)
  2850                              <1> 	; 14/08/2021
  2851                              <1> 	; 12/06/2021
  2852                              <1> 	; 07/06/2020
  2853                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  2854                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2855                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2856                              <1> 	;
  2857                              <1> 	; calculates byte address and bit position for given block number
  2858                              <1> 	; then sets the corresponding bit in the free storage map
  2859                              <1> 	; 
  2860                              <1> 	; INPUTS ->
  2861                              <1> 	;    r1 - block number for a block structured device
  2862                              <1> 	;    cdev - current device 
  2863                              <1> 	; OUTPUTS ->
  2864                              <1> 	;    free storage map is updated
  2865                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2866                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2867                              <1> 	;
  2868                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2869                              <1>         ;  ((Modified registers: DX, CX))  
  2870                              <1> 
  2871                              <1> 	; 27/11/2021
  2872                              <1> 	; INPUT:
  2873                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2874                              <1> 	;	eax = disk block/sector number/address (logical)
  2875                              <1> 	; OUTPUT:
  2876                              <1> 	;	ebx = superblock buffer address
  2877                              <1> 	;
  2878                              <1> 	;    Note:	
  2879                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2880                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2881                              <1> 	;	modification flag will be set; but the superblock 
  2882                              <1> 	;	will not be written to it's disk in this 'free' procedure)
  2883                              <1> 	;
  2884                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp 
  2885                              <1> 
  2886                              <1> 	; 27/11/2021
  2887 00005354 BB[54750000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2888 00005359 F605[89740000]01    <1> 	test	byte [cdev], 1
  2889 00005360 7405                <1> 	jz	short free_1
  2890 00005362 BB[5C770000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2891                              <1> free_1: ; 1
  2892                              <1> 	; 11/02/2022
  2893                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2894 00005367 F6436A01            <1> 	test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2895 0000536B 740F                <1> 	jz	short free_2 
  2896                              <1> 	; 'read only file system' error
  2897 0000536D C705[1C750000]1E00- <1> 	mov	dword [u.error], ERR_READ_ONLY_FS
  2897 00005375 0000                <1>
  2898 00005377 E952E7FFFF          <1> 	jmp	error
  2899                              <1> free_2:
  2900 0000537C 89C1                <1> 	mov	ecx, eax ; logical sector/block number
  2901 0000537E A3[48750000]        <1> 	mov	[free_map_sector], eax
  2902 00005383 C1E903              <1> 	shr	ecx, 3	; convert to fbmap byte offset
  2903 00005386 C1E80C              <1> 	shr	eax, 12 ; convert to fbmap sector index 
  2904                              <1> 			; (1 fb sector for 4096 sectors)
  2905                              <1> 	;and	cl, ~3	; dword alignment (to backward)
  2906                              <1> 	; 11/02/2022
  2907                              <1> 	;and	ecx, 511 ; convert to offset within fbm buffer
  2908 00005389 81E1FC010000        <1> 	and	ecx, 1FCh ; 508, dword aligned offset (32 bit scan)
  2909                              <1> 	;
  2910 0000538F 890D[40750000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm buffer
  2911                              <1> 	; 27/11/2021
  2912                              <1> 	; eax = fbm sector index
  2913 00005395 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2914                              <1> 			; free blocks map start sector address
  2915                              <1> 	; 09/01/2022
  2916 00005398 034304              <1> 	add	eax, [ebx+SB.BootSectAddr]
  2917                              <1> 			; + Hidden Sectors
  2918                              <1> 	; ebx = superblock address
  2919                              <1> 	; eax = physical sector number
  2920 0000539B E8690D0000          <1> 	call	dskrd
  2921                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2922                              <1> 	; eax = physical sector number
  2923                              <1> 	; ebx = buffer data address
  2924                              <1> 	; 27/11/2021
  2925 000053A0 A3[44750000]        <1> 	mov	[free_map_index], eax  ; save physical sector address
  2926 000053A5 8B15[40750000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2927                              <1> 	; 11/02/2022
  2928                              <1> 	;(EDX contains -rounded down- dword aligned offset value)
  2929 000053AB 01DA                <1> 	add	edx, ebx ; + buffer start address
  2930                              <1> 	;
  2931 000053AD 29C0                <1> 	sub	eax, eax
  2932 000053AF A0[48750000]        <1> 	mov	al, [free_map_sector] ; logical sector number
  2933                              <1> 	;and	al, 7
  2934                              <1> 	; 11/02/2022
  2935 000053B4 241F                <1> 	and	al, 31 ; 32 bit fbm scan (with dword aligned offset)
  2936                              <1> 
  2937                              <1> 	; al = bit offset in fbm allocation byte
  2938                              <1> 	; edx = buffer address (start+offset)
  2939                              <1> 	; [free_map_offset] = byte position on fbm
  2940                              <1> 	; 27/11/2021
  2941 000053B6 0FAB02              <1> 	bts	[edx], eax  ; copy value of bit position in eax to cf
  2942                              <1> 			    ; then set same bit position at [edx]
  2943 000053B9 7305                <1> 	jnc	short free_3 ; it was allocated sector
  2944                              <1> 
  2945                              <1> 	; already free sector !? 
  2946                              <1> 	; (nonsence or defective fs)
  2947                              <1> 
  2948 000053BB 30C0                <1> 	xor	al, al ; 0  ; eax = 0
  2949 000053BD 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2950                              <1> 	;mov	[ebx+SB.FreeBlocks], eax 
  2951                              <1> 		; invalidate free blocks count
  2952 000053BE EB18                <1> 	jmp	short free_5
  2953                              <1> free_3:
  2954                              <1> 	; 27/11/2021
  2955 000053C0 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2956 000053C3 40                  <1> 	inc	eax
  2957 000053C4 7401                <1> 	jz	short free_4 ; 0FFFFFFFFh -> 0 (invalid!)
  2958 000053C6 48                  <1> 	dec	eax  ; 0 -> 0FFFFFFFFh (invalid!)
  2959                              <1> free_4: 
  2960 000053C7 50                  <1> 	push	eax ; * ; number of free blocks 
  2961                              <1> 	;mov	eax, [free_map_index] ; fbm sector index
  2962                              <1> 	;add	eax, [ebx+SB.FreeMapAddr] 
  2963                              <1> 			; free blocks map start sector address
  2964                              <1> 	;add	eax, [ebx+SB.BootSectAddr]
  2965                              <1> 	;		; + Hidden Sectors
  2966 000053C8 A1[44750000]        <1> 	mov	eax, [free_map_index] ; restore physical sector address
  2967                              <1> 	; eax = physical sector number
  2968 000053CD E8A90D0000          <1> 	call	wslot
  2969                              <1> 	; ebx = buffer data address (write operation bit is set)
  2970                              <1> 	; eax = physical sector number
  2971                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2972                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2973                              <1> 
  2974 000053D2 E8C00D0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2975                              <1> 		      ; (at the beginning/head of the buffer chain)
  2976                              <1> 
  2977                              <1> 	; if we are here, buffer has been written to disk successfully 
  2978                              <1> 	; (otherwise cpu would jump to 'error' address)
  2979 000053D7 58                  <1> 	pop	eax ; *  ; number of free blocks 
  2980                              <1> free_5:
  2981                              <1> 	; eax = number of free blocks 
  2982                              <1> 	;
  2983                              <1> 	; set superblock modified flag
  2984 000053D8 BA[9C740000]        <1> 	mov	edx, smod
  2985 000053DD BB[54750000]        <1> 	mov	ebx, systm
  2986 000053E2 F605[89740000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2987 000053E9 7406                <1> 	jz	short free_6 ; no, root device
  2988                              <1> 	; yes, mounted device
  2989 000053EB BB[5C770000]        <1> 	mov	ebx, mount
  2990                              <1> 	;mov	edx, mmod
  2991 000053F0 42                  <1> 	inc	edx ; edx = offset mmod
  2992                              <1> free_6: 
  2993 000053F1 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax 
  2994                              <1> 
  2995 000053F4 A1[48750000]        <1> 	mov	eax, [free_map_sector] ; logical sector number
  2996 000053F9 3B433C              <1> 	cmp	eax, [ebx+SB.FirstFreeBlk]
  2997 000053FC 7303                <1> 	jnb	short free_7
  2998 000053FE 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2999                              <1> free_7:
  3000 00005401 FE02                <1> 	inc	byte [edx] ; superblock modified !
  3001 00005403 C3                  <1> 	retn
  3002                              <1> 	
  3003                              <1> iget:
  3004                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3005                              <1> 	; 30/11/2021
  3006                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3007                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3008                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  3009                              <1> 	;
  3010                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  3011                              <1> 	;
  3012                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  3013                              <1> 	; 
  3014                              <1> 	; INPUTS ->
  3015                              <1> 	;    ii - current i-number, rootdir
  3016                              <1> 	;    cdev - new i-node device
  3017                              <1> 	;    idev - current i-node device
  3018                              <1> 	;    imod - current i-node modified flag
  3019                              <1> 	;    mnti - cross device file i-number
  3020                              <1> 	;    r1 - i-numbe rof new i-node
  3021                              <1> 	;    mntd - mountable device number		
  3022                              <1> 	; 	 
  3023                              <1> 	; OUTPUTS ->
  3024                              <1> 	;    cdev, idev, imod, ii, r1
  3025                              <1> 	;
  3026                              <1> 	; ((AX = R1)) input/output
  3027                              <1> 	;
  3028                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3029                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3030                              <1> 
  3031                              <1> 	; 22/11/2021
  3032                              <1> 	;;mov	dl, [cdev] ; 18/07/2013
  3033                              <1> 	;;mov	dh, [idev] ; 07/08/2013
  3034                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3035                              <1> 	;mov	dh, [cdev]
  3036                              <1> 	;mov	dl, [idev]
  3037 00005404 668B15[88740000]    <1> 	mov	dx, [idev] ; [idev] in dl, [cdev] in dh
  3038                              <1> 	;
  3039                              <1> 	; 22/11/2021
  3040 0000540B 25FFFF0000          <1> 	and	eax, 0FFFFh
  3041 00005410 3B05[84740000]      <1> 	cmp 	eax, [ii]
  3042                              <1> 		; cmp r1,ii / r1 = i-number of current file
  3043 00005416 7504                <1> 	jne 	short iget_1
  3044                              <1> 		; bne 1f
  3045 00005418 38F2                <1> 	cmp	dl, dh
  3046                              <1> 		; cmp idev,cdev
  3047                              <1> 			  ; / is device number of i-node = current device
  3048 0000541A 746C                <1>         je	short iget_5
  3049                              <1> 	;	; beq 2f
  3050                              <1> 	; 14/08/2021
  3051                              <1> iget_1: ; 1:
  3052 0000541C 30DB                <1> 	xor	bl, bl
  3053 0000541E 381D[9A740000]      <1> 	cmp	[imod], bl ; 0	
  3054                              <1> 		; tstb imod / has i-node of current file
  3055                              <1> 			  ; / been modified i.e., imod set
  3056 00005424 7628                <1> 	jna	short iget_2
  3057                              <1> 		; beq 1f
  3058 00005426 881D[9A740000]      <1> 	mov	[imod], bl ; 0
  3059                              <1> 		;  clrb	imod / if it has, 
  3060                              <1> 			   ; / we must write the new i-node out on disk
  3061                              <1> 	; 22/11/2021 (32 bit push-pop)
  3062 0000542C 50                  <1> 	push	eax ; *
  3063                              <1> 		; mov r1,-(sp)
  3064 0000542D 52                  <1> 	push	edx ; **
  3065                              <1> 		; mov cdev,-(sp)
  3066 0000542E A1[84740000]        <1> 	mov	eax, [ii]
  3067                              <1> 		; mov ii,r1
  3068                              <1> 	;mov	dh, [idev]
  3069                              <1> 	;mov	[cdev], dh
  3070                              <1> 	; 09/01/2022
  3071 00005433 8815[89740000]      <1> 	mov	[cdev], dl  ; dl = [idev]
  3072                              <1> 		; mov idev,cdev
  3073 00005439 FEC3                <1> 	inc	bl ; 1
  3074                              <1> 	; 31/07/2013
  3075 0000543B 881D[3C750000]      <1> 	mov     [rw], bl ; 1 == write 
  3076                              <1> 	;;28/07/2013 rw -> u.rw
  3077                              <1>         ;;mov   [u.rw], bl ; 1 == write
  3078 00005441 E843000000          <1> 	call	icalc
  3079                              <1> 		; jsr r0,icalc; 1
  3080 00005446 5A                  <1> 	pop	edx ; **
  3081 00005447 8835[89740000]      <1> 	mov	[cdev], dh ; 22/11/2021
  3082                              <1> 		; mov (sp)+,cdev
  3083 0000544D 58                  <1> 	pop	eax ; *
  3084                              <1> 		; mov (sp)+,r1
  3085                              <1> iget_2: ; 1:
  3086                              <1> 	;and	ax, ax
  3087 0000544E 21C0                <1> 	and	eax, eax ; 22/11/2021 (32 bit inode number)
  3088                              <1> 		; tst r1 / is new i-number non zero
  3089 00005450 7431                <1> 	jz	short iget_4 ; 2f
  3090                              <1> 		; beq 2f / branch if r1=0
  3091                              <1> 
  3092                              <1> 	;mov 	dh, [cdev]
  3093 00005452 08F6                <1> 	or	dh, dh ; 22/11/2021
  3094                              <1> 		; tst cdev / is the current device number non zero
  3095                              <1> 			 ; / (i.e., device =/ drum)
  3096 00005454 7515                <1> 	jnz	short iget_3 ;  1f
  3097                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  3098                              <1> 	; 22/11/2021
  3099 00005456 3B05[94740000]      <1> 	cmp	eax, [mnti]
  3100                              <1> 	;cmp	ax, [mnti]			
  3101                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  3102                              <1> 			    ; / file (root directory of mounted device)
  3103 0000545C 750D                <1> 	jne	short iget_3 ; 1f
  3104                              <1> 		; bne 1f
  3105                              <1>         ;mov    bl, [mntd]
  3106 0000545E FEC6                <1> 	inc	dh ; mov dh, 1 ; 22/11/2021
  3107 00005460 8835[89740000]      <1>         mov	[cdev], dh ; 22/11/2021
  3108                              <1> 		; mov mntd,cdev / make mounted device the current device
  3109                              <1> 	; 22/11/2021
  3110 00005466 A1[90740000]        <1> 	mov	eax, [rootdir] ; rootdir = 1 (for runix v2 file system)
  3111                              <1> 	;mov	ax, [rootdir]
  3112                              <1> 		; mov rootdir,r1
  3113                              <1> iget_3: ; 1:
  3114                              <1> 	; 22/11/2021
  3115 0000546B A3[84740000]        <1> 	mov	[ii], eax ; 32 bit inode number
  3116                              <1> 	;mov	[ii], ax
  3117                              <1> 		; mov r1,ii
  3118                              <1> 	; 30/11/2021
  3119 00005470 8835[88740000]      <1> 	mov	[idev], dh ; cdev 
  3120                              <1> 	;mov	[idev], dl ; cdev
  3121                              <1> 		; mov cdev,idev
  3122 00005476 30DB                <1> 	xor	bl, bl
  3123                              <1>         ; 31/07/2013
  3124 00005478 881D[3C750000]      <1> 	mov     [rw], bl ; 0 == read 
  3125                              <1> 	;;28/07/2013 rw -> u.rw       
  3126                              <1>         ;;mov   [u.rw], bl ; 0 = read
  3127 0000547E E806000000          <1> 	call	icalc
  3128                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  3129                              <1> iget_4: ; 2:
  3130                              <1> 	; 22/11/2021
  3131 00005483 A1[84740000]        <1> 	mov	eax, [ii]
  3132                              <1> 	;mov	ax, [ii]
  3133                              <1> 		; mov ii,r1
  3134                              <1> iget_5:
  3135 00005488 C3                  <1> 	retn
  3136                              <1> 		; rts r0
  3137                              <1> 
  3138                              <1> icalc:
  3139                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3140                              <1> 	; 28/11/2021
  3141                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 
  3142                              <1> 	; 02/07/2015
  3143                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3144                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3145                              <1> 	;
  3146                              <1> 	; calculate physical block number from i-number then
  3147                              <1> 	; read or write that block
  3148                              <1> 	;
  3149                              <1> 	; 'icalc' is called from 'iget'
  3150                              <1> 	;
  3151                              <1> 	; for original unix v1:
  3152                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  3153                              <1>        	; / (i+31.) mod 16. bytes from its start
  3154                              <1> 	;
  3155                              <1> 	; for retro unix 8086 v1:
  3156                              <1> 	;  i-node is located in block (i+47)/16 and
  3157                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  3158                              <1> 	;
  3159                              <1> 	; INPUTS ->
  3160                              <1> 	;    r1 - i-number of i-node
  3161                              <1> 	; 	 
  3162                              <1> 	; OUTPUTS ->
  3163                              <1> 	;    inode r/w
  3164                              <1> 	;
  3165                              <1> 	; ((AX = R1)) input
  3166                              <1> 	;
  3167                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3168                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  3169                              <1> 	;
  3170                              <1> 
  3171                              <1> 	; 28/11/2021
  3172                              <1> 	;cmp	byte [idev], 0 ; [cdev] = [idev]
  3173 00005489 803D[89740000]00    <1> 	cmp	byte [cdev], 0
  3174 00005490 7607                <1> 	jna	short icalc_0r
  3175 00005492 BD[5C770000]        <1> 	mov	ebp, mount  ; mounted file system's superblock 
  3176 00005497 EB05                <1> 	jmp	short icalc_0m
  3177                              <1> icalc_0r:
  3178                              <1> 	; 28/11/2021
  3179 00005499 BD[54750000]        <1> 	mov	ebp, systm  ; root file system's superblock 
  3180                              <1> icalc_0m:
  3181                              <1> 	; 22/11/2021
  3182                              <1> 	;mov	edx, eax
  3183 0000549E 8B15[84740000]      <1> 	mov	edx, [ii] ; 32 bit inode number
  3184 000054A4 8B4528              <1> 	mov	eax, [ebp+SB.InodeTblAddr] ; inode table base address
  3185                              <1> 	;
  3186 000054A7 4A                  <1> 	dec	edx ; 0 based inode number 
  3187                              <1> 		    ; (inode index in inode table)
  3188 000054A8 52                  <1> 	push	edx ; *
  3189 000054A9 C1EA03              <1> 	shr	edx, 3
  3190 000054AC 7402                <1> 	jz	short icalc_0t ; 0 for inodes 1 to 8
  3191 000054AE 01D0                <1> 	add	eax, edx
  3192                              <1> icalc_0t:
  3193                              <1> 	; 09/01/2022
  3194                              <1> 	; eax = locical block/sector number 
  3195 000054B0 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  3196                              <1> 	; eax = physical block/sector number 
  3197 000054B3 E8510C0000          <1> 	call	dskrd
  3198                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  3199                              <1> 	; 31/07/2013
  3200 000054B8 803D[3C750000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  3201                              <1> 	;; 28/07/2013 rw -> u.rw
  3202                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  3203                              <1> 		; tst (r0)
  3204 000054BF 7605                <1> 	jna	short icalc_1
  3205                              <1> 		; beq 1f / branch to wslot when argument
  3206                              <1> 		       ; / in icalc call = 1
  3207                              <1> 	; eAX = r1 = block number
  3208 000054C1 E8B50C0000          <1> 	call	wslot
  3209                              <1> 		; jsr r0,wslot / set up data buffer for write
  3210                              <1> 			     ; / (will be same buffer as dskrd got)
  3211                              <1> 	; EBX = r5 points to first word in data area for this block
  3212                              <1> icalc_1: ; 1:
  3213 000054C6 5A                  <1> 	pop	edx ; *
  3214                              <1> 	; 22/11/2021
  3215 000054C7 83E207              <1> 	and 	edx, 07h ; 8 inodes per inode table sector
  3216 000054CA C1E206              <1> 	shl 	edx, 6 ; * 64 (inode size)
  3217                              <1> 	; edx = 64 * (mod(inodenumber-1)/8)
  3218 000054CD 89DE                <1> 	mov	esi, ebx  ; ebx points to 1st word of the buffer
  3219 000054CF 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  3220                              <1>           	; eSI (r5) points to first word in i-node i.	
  3221                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  3222                              <1> 			     ; / 32.*(i+31.)mod16
  3223                              <1> 		; mov $5,lsh / for i-node i.
  3224                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  3225 000054D1 BF[44700000]        <1> 	mov	edi, inode
  3226                              <1> 		; mov $inode,r1 / inode is address of first word 
  3227                              <1> 			      ; / of current i-node
  3228                              <1> 	;mov 	ecx, 8 ; 02/07/2015 (32 bit modification)
  3229                              <1> 	;	; mov $16.,r3
  3230                              <1> 	; 28/11/2021
  3231 000054D6 29C9                <1> 	sub	ecx, ecx
  3232 000054D8 B110                <1> 	mov	cl, 16 ; Retro UNIX 386 v2 inode size = 64 bytes
  3233                              <1> 	; 31/07/2013
  3234 000054DA 382D[3C750000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3235                              <1>        ;;28/07/2013 rw -> u.rw                 
  3236                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3237                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  3238 000054E0 7609                <1> 	jna	short icalc_3
  3239                              <1> 		; beq 2f / r0 now contains proper return address 
  3240                              <1> 		       ; / for rts r0
  3241                              <1> icalc_2: ; 1:
  3242 000054E2 87F7                <1> 	xchg 	esi, edi
  3243                              <1> 	; overwrite old i-node (in buffer to be written)
  3244 000054E4 F3A5                <1> 	rep 	movsd
  3245                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  3246                              <1> 		; dec r3
  3247                              <1> 		; bgt 1b
  3248                              <1> 	;call	dskwr
  3249                              <1> 	;	; jsr r0,dskwr / write inode out on device
  3250                              <1> 	;retn
  3251                              <1> 	;	; rts r0
  3252                              <1> 	; 28/11/2021
  3253 000054E6 E9AC0C0000          <1> 	jmp	dskwr
  3254                              <1> icalc_3: ; 2:
  3255                              <1> 	; copy new i-node into inode area of (core) memory
  3256 000054EB F3A5                <1> 	rep 	movsd
  3257                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  3258                              <1> 		                ; / "inode" area of core
  3259                              <1> 		; dec r3
  3260                              <1> 		; bgt 2b
  3261 000054ED C3                  <1> 	retn
  3262                              <1> 		; rts r0
  3263                              <1> 
  3264                              <1> access:
  3265                              <1> 	; 25/12/2021
  3266                              <1> 	; 19/12/2021
  3267                              <1> 	; 28/11/2021
  3268                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3269                              <1> 	; 31/10/2021 - temporary (simplified code)
  3270                              <1> 	; 14/06/2021
  3271                              <1> 	; 02/05/2021
  3272                              <1> 	; 27/03/2021
  3273                              <1> 	; 26/03/2021
  3274                              <1> 	; 25/03/2021
  3275                              <1> 	; 23/03/2021 (Retro UNIX 386 v2 - Beginning)
  3276                              <1> 	;	((ref: unix v7 source - fio.c))
  3277                              <1> 	; ref: INODE STRUCTURE of Retro UNIX v2 file system
  3278                              <1> 	;	07/02/2020, 'RETRO UNIX v2 Inodes.pdf'
  3279                              <1> 	;	 
  3280                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3281                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3282                              <1> 	;
  3283                              <1> 	; check whether user is owner of file or user has read or write
  3284                              <1> 	; permission (based on i.flgs).
  3285                              <1> 	;
  3286                              <1> 	; INPUTS ->
  3287                              <1> 	;    r1 - i-number of file
  3288                              <1> 	;    u.uid
  3289                              <1> 	; arg0 -> (owner flag mask)	 		
  3290                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  3291                              <1> 	; OUTPUTS ->
  3292                              <1> 	;    inode (or jump to error)
  3293                              <1> 	;
  3294                              <1> 	; ((AX = R1)) input/output
  3295                              <1> 	;
  3296                              <1> 	;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))
  3297                              <1> 
  3298                              <1> 	; 26/03/2021
  3299                              <1> 	; INPUT:
  3300                              <1> 	;	eax = inode number (ax)
  3301                              <1> 	;	 dx = mode (IEXEC, IREAD or IWRITE) 
  3302                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3303                              <1> 	;	
  3304                              <1> 	; OUTPUT:
  3305                              <1> 	;	inode (or jump to error)
  3306                              <1> 	;	eax (ax) = [ii] = inode number
  3307                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3308                              <1> 	;
  3309                              <1> 	; Modified registers: (eax), ebx, ecx, edx, esi, edi, ebp
  3310                              <1> 	;
  3311                              <1> 	; IREAD	 equ 100h ; read permission flag, owner
  3312                              <1> 	; IWRITE equ 80h  ; write permission flag, owner
  3313                              <1> 	; IEXEC	 equ 40h  ; execute permission flag, owner	 
  3314                              <1> 		
  3315                              <1> 	; 23/03/2021
  3316 000054EE 52                  <1> 	push	edx ; save flag (DX)
  3317                              <1> 	;push	dx  ; save flag (DL)
  3318 000054EF E810FFFFFF          <1> 	call	iget
  3319                              <1> 		; jsr r0,iget / read in i-node for current directory
  3320                              <1> 			    ; / (i-number passed in r1)
  3321                              <1> 	;;mov	cl, [i.flgs]
  3322                              <1> 	;;	; mov i.flgs,r2
  3323                              <1> 	; 23/03/2021
  3324                              <1> 	;mov	cx, [i.flgs]	
  3325                              <1> 
  3326                              <1> 	;;pop	dx  ; restore flag (DL)
  3327                              <1> 	; 23/03/2021
  3328 000054F4 5A                  <1> 	pop	edx ; restore flag (DX)
  3329                              <1> 
  3330                              <1> 	; 28/11/2021 (iget will not return here if there is an error)
  3331                              <1> 	; 31/10/2021
  3332                              <1> 	;jc	short access_5
  3333                              <1> 
  3334                              <1> 	; 31/10/2021
  3335                              <1> 	; Note: If eax input is same with [mnti], 'iget' will change
  3336                              <1> 	; [cdev] to 1 and eax will be 1 (root dir of mounted fs) 
  3337                              <1> 
  3338                              <1> 	; 27/03/2021
  3339                              <1> 	; 23/03/2021
  3340                              <1> 	; (check if it is write permission flag)
  3341 000054F5 6681FA8000          <1> 	cmp	dx, 80h ; IWRITE
  3342 000054FA 775E                <1> 	ja	short access_r	; IREAD = 100h (owner)
  3343 000054FC 722B                <1> 	jb	short access_x	; IEXEC = 40h (owner)
  3344                              <1> 	; IWRITE (80h)
  3345                              <1> access_w:
  3346                              <1> 	; 23/03/2021
  3347                              <1> 	; ((ref: Retro UNIX 386 v2, 'ux.s', 'ldrv' structure))
  3348                              <1> 	;mov	bl, [idev]
  3349                              <1> 	;call	getfs
  3350                              <1>  	;movzx	ebx, byte [idev]  ; logical drive number
  3351                              <1> 	;shl	bx, 6 ; * 64	  ; of current inode	
  3352                              <1> 	;add	ebx, ldrvtable	
  3353                              <1> 	;;test	byte [ebx+ldrv.pflags], 01h ; read only fs flag
  3354                              <1> 	;;jz	short access_0
  3355                              <1> 	;; 14/06/2021
  3356                              <1> 	; 14/06/2021
  3357                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3358                              <1> 	;mov	edi, [ebx+ldrv.superblk]
  3359                              <1> 	;test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3360                              <1> 	;jz	short access_0
  3361                              <1> 	; 31/10/2021
  3362 000054FE 803D[89740000]01    <1> 	cmp	byte [cdev], 1
  3363 00005505 7207                <1> 	jb	short access_7 ; [cdev] = 0
  3364                              <1> 	; [cdev] = 1
  3365                              <1> 	; 28/11/2021
  3366 00005507 BF[5C770000]        <1> 	mov	edi, mount ; mounted file system's superblock buffer
  3367 0000550C EB05                <1> 	jmp	short access_8
  3368                              <1> access_7:
  3369                              <1> 	; 28/11/2021
  3370 0000550E BF[54750000]        <1> 	mov	edi, systm ; root file system's superblock buffer
  3371                              <1> access_8:
  3372 00005513 F6476A01            <1> 	test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3373 00005517 7441                <1> 	jz	short access_0
  3374                              <1> 
  3375                              <1> 	; 23/03/2021
  3376                              <1> 	;mov	dword [u.error], ERR_READ_ONLY_FS
  3377                              <1> 	;		; 'read only file system !' error
  3378                              <1> 	;jmp	error
  3379                              <1> 
  3380                              <1> 	; 19/12/2021
  3381 00005519 F605[45700000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  3382 00005520 7438                <1> 	jz	short access_0  ; no, device file
  3383                              <1> 
  3384                              <1> 	; 31/10/2021
  3385 00005522 B81E000000          <1> 	mov	eax, ERR_READ_ONLY_FS
  3386                              <1> 			; 'read only file system !' error
  3387                              <1> 	; 27/03/2021
  3388 00005527 EB27                <1> 	jmp	short access_5
  3389                              <1> 
  3390                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3391                              <1> 
  3392                              <1> 	;mov	dh, [u.uid]
  3393                              <1> 	;cmp	dh, [i.uid]
  3394                              <1> 	;	; cmpb i.uid,u.uid / is user same as owner of file
  3395                              <1> 	;jne	short access_1
  3396                              <1> 		; bne 1f / no, then branch
  3397                              <1> access_x:
  3398                              <1> 	; IEXEC (40h)
  3399                              <1> 	; 27/03/2021
  3400 00005529 668B1D[44700000]    <1> 	mov	bx, [i.flgs]
  3401 00005530 F6C780              <1> 	test	bh, 80h ; regular file ?
  3402 00005533 7416                <1> 	jz	short access_4 ; not executable file !
  3403 00005535 F6C740              <1> 	test	bh, 40h	; directory ?
  3404 00005538 7511                <1> 	jnz	short access_4 ; not executable file !
  3405 0000553A 668B0D[FA740000]    <1> 	mov	cx, [u.uid]
  3406 00005541 6609C9              <1> 	or	cx, cx
  3407 00005544 7520                <1> 	jnz	short access_3 ; (restricted user)
  3408                              <1> 	; (super user)
  3409                              <1> 	;test	[i.flgs], dl ; execute permission for owner
  3410                              <1> 	;test	byte [i.flgs], 49h ; for owner, group, others
  3411 00005546 F6C349              <1> 	test	bl, 49h ; exec perm for owner, group, others
  3412 00005549 7557                <1> 	jnz	short access_2
  3413                              <1> access_4:
  3414                              <1> 	; 31/10/2021
  3415 0000554B B816000000          <1> 	mov	eax, ERR_NOT_EXECUTABLE
  3416                              <1> 			; 'not executable file !' error
  3417                              <1> 	; 26/03/2021
  3418                              <1> ;;sysexec_not_exf:
  3419                              <1> ;	mov	dword [u.error], ERR_NOT_EXECUTABLE
  3420                              <1> ;			; 'not executable file !' error
  3421                              <1> ;access_5:
  3422                              <1> ;	jmp	error
  3423                              <1> 	
  3424                              <1> 	; 31/10/2021
  3425                              <1> access_5:
  3426 00005550 A3[1C750000]        <1> 	mov	[u.error], eax
  3427 00005555 E974E5FFFF          <1> 	jmp	error
  3428                              <1> 
  3429                              <1> access_r:
  3430                              <1> 	; 27/03/2021
  3431                              <1> access_0:
  3432                              <1> 	; 23/03/2021
  3433 0000555A 668B0D[FA740000]    <1> 	mov	cx, [u.uid]
  3434 00005561 6609C9              <1> 	or	cx, cx ; 0 ; root ?
  3435                              <1> 	;jz	short access_2 ; yes
  3436                              <1> 	; 25/12/2021
  3437 00005564 742C                <1> 	jz	short access_1 ; yes
  3438                              <1> access_3:
  3439                              <1> 	; owner ?
  3440 00005566 8A1D[4A700000]      <1> 	mov	bl, [i.gid]
  3441 0000556C 663B0D[48700000]    <1> 	cmp	cx, [i.uid]
  3442                              <1> 	;je	short access_1
  3443                              <1> 	; 02/05/2021
  3444 00005573 750E                <1> 	jne	short access_6
  3445                              <1> 	; check owner's group number/ID
  3446 00005575 3A1D[FE740000]      <1> 	cmp	bl, [u.gid] ; same group number/ID ?
  3447 0000557B 7415                <1> 	je	short access_1 ; yes, owner
  3448                              <1> 	; one of others
  3449 0000557D 66C1EA06            <1> 	shr	dx, 6
  3450 00005581 EB0F                <1> 	jmp	short access_1 ; others
  3451                              <1> access_6:
  3452                              <1> 	;shr	cl, 2
  3453                              <1> 	;	; asrb r2 / shift owner read write bits into non owner
  3454                              <1> 	;	;       ; / read/write bits
  3455                              <1> 	;	; asrb r2
  3456                              <1> 
  3457                              <1> 	; 23/03/2021
  3458                              <1> 	; same group ?
  3459 00005583 66C1EA03            <1> 	shr	dx, 3
  3460                              <1> 	;mov	cl, [u.gid]
  3461                              <1> 	;cmp	cl, [i.gid]
  3462                              <1> 	;je	short access_1
  3463                              <1> 	; 02/05/2021
  3464 00005587 3A1D[FE740000]      <1> 	cmp	bl, [u.gid]
  3465 0000558D 7403                <1> 	je	short access_1 ; same group, different owner
  3466                              <1> 
  3467                              <1> 	; others
  3468                              <1> 	;shr	dx, 3
  3469 0000558F C0EA03              <1> 	shr	dl, 3
  3470                              <1> 	;jmp	short access_1	
  3471                              <1> 
  3472                              <1> ;access_1: ; 1:
  3473                              <1> 	;and	cl, dl
  3474                              <1> 	;	; bit r2,(r0)+ / test read-write flags against argument
  3475                              <1> 	;		     ; / in access call
  3476                              <1> 	;jnz	short access_2
  3477                              <1> 	;	; bne 1f
  3478                              <1> 	
  3479                              <1> 	;or	dh, dh	; super user (root) ?
  3480                              <1> 	;	; tstb u.uid
  3481                              <1> 	;jz	short access_2 ; yes, super user
  3482                              <1> 	;;jnz	error
  3483                              <1> 	;	; beq 1f
  3484                              <1> 	;	; jmp error
  3485                              <1> 	
  3486                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3487                              <1> 	;		; 'permission denied !' error
  3488                              <1> 	;jmp	error
  3489                              <1> 
  3490                              <1> access_1:
  3491                              <1> 	; 23/03/2021
  3492 00005592 668515[44700000]    <1> 	test	dx, [i.flgs]
  3493 00005599 7507                <1> 	jnz	short access_2
  3494                              <1> 
  3495                              <1> 	;; r/w permission error
  3496                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3497                              <1> 	;		; 'permission denied !' error
  3498                              <1> 	;;jmp	error
  3499                              <1> 
  3500                              <1> 	; 31/10/2021
  3501 0000559B B80B000000          <1> 	mov	eax, ERR_FILE_ACCESS 
  3502                              <1> 			; 'permission denied !' error
  3503                              <1> 	; 27/03/2021
  3504 000055A0 EBAE                <1> 	jmp	short access_5
  3505                              <1> 
  3506                              <1> access_2: ; 1:
  3507                              <1> 	;; DL = flags
  3508                              <1> 	;retn
  3509                              <1> 	;	; rts r0
  3510                              <1> 	; 27/03/2021
  3511                              <1> 	; DX = flag (100h-20h-04h or 80h-10h-02h or 40h-08h-01h)
  3512 000055A2 C3                  <1> 	retn
  3513                              <1> 
  3514                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  3515                              <1> %if 0
  3516                              <1> 
  3517                              <1> setimod:
  3518                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3519                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3520                              <1> 	;
  3521                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3522                              <1> 	; the inode has been modified. Also puts the time of modification
  3523                              <1> 	; into the inode.
  3524                              <1> 	;
  3525                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3526                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3527                              <1> 	;
  3528                              <1> 	
  3529                              <1> 	; push 	edx
  3530                              <1> 	push	eax
  3531                              <1> 
  3532                              <1> 	mov 	byte [imod], 1
  3533                              <1> 		; movb $1,imod / set current i-node modified bytes
  3534                              <1> 	; Erdogan Tan 14-7-2012
  3535                              <1> 	call 	epoch
  3536                              <1> 		 ; mov s.time,i.mtim 
  3537                              <1> 			    ; / put present time into file modified time
  3538                              <1> 		 ; mov s.time+2,i.mtim+2
  3539                              <1> 
  3540                              <1> 	mov 	[i.mtim], eax
  3541                              <1> 	
  3542                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3543                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3544                              <1> 	cmp	dword [i.ctim], 0
  3545                              <1> 	jnz	short setimod_ok
  3546                              <1> 
  3547                              <1> 	mov 	[i.ctim], eax
  3548                              <1> 
  3549                              <1> setimod_ok: ; 31/07/2013
  3550                              <1> 	pop	eax
  3551                              <1> 	;pop	edx
  3552                              <1> 	
  3553                              <1> 	retn
  3554                              <1> 		; rts r0
  3555                              <1> %endif
  3556                              <1> 
  3557                              <1> setimod:
  3558                              <1> 	; 12/01/2022 - Retro UNIX 386 v1.2
  3559                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3560                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3561                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3562                              <1> 	;
  3563                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3564                              <1> 	; the inode has been modified. Also puts the time of modification
  3565                              <1> 	; into the inode.
  3566                              <1> 	;
  3567                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3568                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3569                              <1> 	;
  3570                              <1> 
  3571                              <1> 	; Reference:
  3572                              <1> 	; 25/01/2020 - 'UNIXHDCP.ASM', 'setimod' procedure
  3573                              <1> 	;	(Retro UNIX 386 v2 file system installation utility)
  3574                              <1> 
  3575                              <1> 	; 25/05/2020
  3576                              <1> 	;
  3577                              <1> 	; INPUT:
  3578                              <1> 	;	none
  3579                              <1> 	; OUTPUT:
  3580                              <1> 	;	inode times and [imod] will be set
  3581                              <1> 	;	      ([imodx] will be reset)
  3582                              <1> 	;	cf = 0 	
  3583                              <1> 
  3584                              <1> 	; Modified registers: ecx, (edx)?
  3585                              <1> 	
  3586                              <1> 	;push 	edx
  3587 000055A3 50                  <1> 	push	eax
  3588                              <1> 
  3589 000055A4 C605[9A740000]01    <1> 	mov 	byte [imod], 1
  3590                              <1> 		; movb $1,imod / set current i-node modified bytes
  3591                              <1> 
  3592                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3593 000055AB A1[80700000]        <1> 	mov	eax, [i.ctim] ; inode (file) creation time
  3594 000055B0 21C0                <1> 	and	eax, eax
  3595 000055B2 7518                <1> 	jnz	short setimod_4
  3596                              <1> 
  3597                              <1> 	; New file
  3598                              <1> setimod_1:
  3599                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 by Erdogan Tan
  3600                              <1> 	;	 (Modified UNIX v7 inode and new FS construction) 	
  3601                              <1> 	;
  3602 000055B4 E8A60C0000          <1> 	call	get_system_time ; get current (unix epoch) time
  3603                              <1> 
  3604                              <1> 	;; Erdogan Tan 14-7-2012
  3605                              <1> 	;call 	epoch
  3606                              <1> 	;	 ; mov s.time,i.mtim 
  3607                              <1> 	;		    ; / put present time into file modified time
  3608                              <1> 	;	 ; mov s.time+2,i.mtim+2
  3609                              <1> 	;
  3610                              <1> 	;mov 	[i.mtim], eax
  3611                              <1> 
  3612                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3613                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3614                              <1> 	;cmp	dword [i.ctim], 0
  3615                              <1> 	;jnz	short setimod_ok
  3616                              <1> 		
  3617 000055B9 A3[80700000]        <1> 	mov 	[i.ctim], eax
  3618                              <1> 	
  3619                              <1> 	; 25/05/2020
  3620 000055BE EB05                <1> 	jmp	short setimod_3
  3621                              <1> 
  3622                              <1> setimod_2:
  3623                              <1> 	; File/Directory data (file size or content) is changed
  3624                              <1> 	; This is last modification date&time
  3625 000055C0 A3[7C700000]        <1> 	mov	[i.mtim], eax
  3626                              <1> setimod_3:
  3627                              <1> 	; 19/09/2019 ('UNIXHDCP.ASM', 'setimod' by Erdogan Tan)
  3628                              <1> 	; This is last access or last changing date&time
  3629                              <1> 	; of inode (chmod,chown,chgrp,link)
  3630                              <1> 	; parameters (without file/dir data changing)
  3631 000055C5 A3[78700000]        <1> 	mov	[i.atim], eax
  3632                              <1> 
  3633                              <1> setimod_ok: ; 31/07/2013
  3634 000055CA 58                  <1> 	pop	eax
  3635                              <1> 	;pop	edx
  3636                              <1> 	
  3637 000055CB C3                  <1> 	retn
  3638                              <1> 		; rts r0
  3639                              <1> setimod_4:
  3640                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  3641 000055CC 31C9                <1> 	xor	ecx, ecx
  3642 000055CE 390D[7C700000]      <1> 	cmp	[i.mtim], ecx ; 0
  3643 000055D4 76EA                <1> 	jna	short setimod_2
  3644                              <1> 
  3645 000055D6 E8840C0000          <1> 	call	get_system_time ; get current (unix epoch) time
  3646                              <1> 	; ((system time will be updated directly by timer interrupt))
  3647                              <1> 
  3648 000055DB 803D[9B740000]00    <1> 	cmp	byte [imodx], 0 ; flag means "file/dir data is same but
  3649 000055E2 76DC                <1> 	jna	short setimod_2 ; inode has been changed"
  3650                              <1> 
  3651                              <1> 	; File/Dir data (File size or content) is same but
  3652                              <1> 	; inode's mode, link count, owner or group id has been changed
  3653                              <1> 	; (so, we do not change last modification date&time)
  3654 000055E4 C605[9B740000]00    <1> 	mov	byte [imodx], 0 ; reset inode modified (extended) flag
  3655 000055EB EBD8                <1> 	jmp	short setimod_3
  3656                              <1> 
  3657                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  3658                              <1> %if 0
  3659                              <1> 	; Retro UNIX 386 v1.1 'itrunc' code
  3660                              <1> itrunc:
  3661                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3662                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  3663                              <1> 	;
  3664                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3665                              <1> 	;  to zero length.
  3666                              <1> 	;
  3667                              <1> 	; INPUTS ->
  3668                              <1> 	;    r1 - i-number of i-node
  3669                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  3670                              <1> 	;    i.flgs - large file flag		
  3671                              <1> 	;    i.size - size of file	
  3672                              <1> 	; 	 
  3673                              <1> 	; OUTPUTS ->
  3674                              <1> 	;    i.flgs - large file flag is cleared
  3675                              <1> 	;    i.size - set to 0	
  3676                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  3677                              <1> 	;    setimod - set to indicate i-node has been modified
  3678                              <1> 	;    r1 - i-number of i-node  					
  3679                              <1> 	;
  3680                              <1> 	; ((AX = R1)) input/output
  3681                              <1> 	;
  3682                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  3683                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3684                              <1> 
  3685                              <1> 	call	iget
  3686                              <1> 		; jsr r0,iget
  3687                              <1> 	mov	esi, i.dskp
  3688                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  3689                              <1> 	xor	eax, eax
  3690                              <1> itrunc_1: ; 1:
  3691                              <1> 	lodsw
  3692                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  3693                              <1> 	or 	ax, ax
  3694                              <1> 	jz	short itrunc_5
  3695                              <1> 		; beq 5f
  3696                              <1> 	push	esi
  3697                              <1> 		; mov r2,-(sp)
  3698                              <1> 	test    word [i.flgs], 1000h    
  3699                              <1> 		; bit $10000,i.flgs / test large file bit?
  3700                              <1> 	jz	short itrunc_4
  3701                              <1> 		; beq 4f / if clear, branch
  3702                              <1> 	push	eax
  3703                              <1> 		; mov r1,-(sp) / save block number of indirect block
  3704                              <1> 	call	dskrd
  3705                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  3706                              <1> 			     ; / pointed to by r5
  3707                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  3708                              <1> 	mov	ecx, 256
  3709                              <1> 		; mov $256.,r3 / move word count into r3
  3710                              <1> 	mov	esi, ebx
  3711                              <1> itrunc_2: ; 2:
  3712                              <1> 	lodsw
  3713                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  3714                              <1> 			     ; / physical block number
  3715                              <1> 	and	ax, ax
  3716                              <1> 	jz	short itrunc_3
  3717                              <1> 		; beq 3f / branch if zero
  3718                              <1> 	;push	ecx
  3719                              <1> 	push	cx
  3720                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3721                              <1> 	;push	esi
  3722                              <1> 		; mov r5,-(sp)
  3723                              <1> 	call	free
  3724                              <1> 		; jsr r0,free / free block in free storage map
  3725                              <1> 	;pop	esi
  3726                              <1> 		; mov(sp)+,r5
  3727                              <1> 	pop	cx
  3728                              <1> 	;pop	ecx
  3729                              <1> 		; mov (sp)+,r3
  3730                              <1> itrunc_3: ; 3:
  3731                              <1> 	loop	itrunc_2
  3732                              <1> 		; dec r3 / decrement word count
  3733                              <1> 		; bgt 2b / branch if positive
  3734                              <1> 	pop	eax
  3735                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3736                              <1> 			     ; / indirect block
  3737                              <1> 	; 01/08/2013
  3738                              <1>         and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3739                              <1> itrunc_4: ; 4:
  3740                              <1> 	call	free
  3741                              <1> 		; jsr r0,free / free indirect block
  3742                              <1> 	pop	esi
  3743                              <1> 		; mov (sp)+,r2
  3744                              <1> itrunc_5: ; 5:
  3745                              <1> 	cmp	esi, i.dskp+16
  3746                              <1> 		; cmp r2,$i.dskp+16.
  3747                              <1> 	jb	short itrunc_1	
  3748                              <1> 		; bne 1b / branch until all i.dskp entries check
  3749                              <1> 	; 01/08/2013
  3750                              <1> 	;and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3751                              <1> 		; bic $10000,i.flgs / clear large file bit
  3752                              <1> 	mov	edi, i.dskp
  3753                              <1> 	mov	cx, 8
  3754                              <1> 	xor 	ax, ax
  3755                              <1> 	mov	[i.size], ax ; 0
  3756                              <1> 		; clr i.size / zero file size
  3757                              <1> 	rep	stosw
  3758                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3759                              <1> 			   ; / zero block pointers
  3760                              <1> 	call	setimod
  3761                              <1> 		; jsr r0,setimod / set i-node modified flag
  3762                              <1> 	mov	ax, [ii]
  3763                              <1> 		; mov ii,r1
  3764                              <1> 	retn
  3765                              <1> 		; rts r0
  3766                              <1> 
  3767                              <1> 	; Retro UNIX 386 v1.1 'imap' code
  3768                              <1> imap:
  3769                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3770                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3771                              <1> 	;
  3772                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3773                              <1> 	; allocation bit for an i-node whose number in r1.
  3774                              <1> 	;
  3775                              <1> 	; INPUTS ->
  3776                              <1> 	;    r1 - contains an i-number
  3777                              <1> 	;    fsp - start of table containing open files
  3778                              <1> 	;
  3779                              <1> 	; OUTPUTS ->
  3780                              <1> 	;    r2 - byte address of byte with the allocation bit
  3781                              <1> 	;    mq - a mask to locate the bit position.	
  3782                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3783                              <1> 	;
  3784                              <1> 	; ((AX = R1)) input/output
  3785                              <1> 	; ((DL/DX = MQ)) output
  3786                              <1> 	; ((BX = R2)) output
  3787                              <1> 	;
  3788                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3789                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3790                              <1> 	;
  3791                              <1> 		; / get the byte that has the allocation bit for 
  3792                              <1> 		; / the i-number contained in r1
  3793                              <1> 	;mov	dx, 1
  3794                              <1> 	mov	dl, 1
  3795                              <1> 		; mov $1,mq / put 1 in the mq
  3796                              <1> 	movzx	ebx, ax
  3797                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3798                              <1>  		          ; / in the map we must find
  3799                              <1> 	sub	bx, 41
  3800                              <1> 		; sub $41.,r2 / r2 has i-41
  3801                              <1> 	mov	cl, bl
  3802                              <1> 		; mov r2,r3 / r3 has i-41
  3803                              <1> 	and	cl, 7
  3804                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3805                              <1> 			   ; / the bit position
  3806                              <1> 	jz	short imap1
  3807                              <1> 	;shl	dx, cl
  3808                              <1> 	shl	dl, cl
  3809                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3810                              <1> imap1:			   ; / to the left to mask the correct bit
  3811                              <1> 	shr	bx, 3
  3812                              <1> 		; asr r2
  3813                              <1> 		; asr r2
  3814                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3815                              <1> 		       ; / from the start of the map
  3816                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3817                              <1> 	mov	esi, systm
  3818                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3819                              <1> 				; / the super block for drum
  3820                              <1> 	;cmp	word [cdev], 0
  3821                              <1> 	cmp	byte [cdev], 0
  3822                              <1> 		; tst cdev / is the device the disk
  3823                              <1> 	jna	short imap2
  3824                              <1> 		; beq 1f / yes
  3825                              <1> 	add	esi, mount - systm
  3826                              <1> 		; add $mount-systm,r2 / for mounted device,
  3827                              <1> 			; / r2 points to 1st word of its super block
  3828                              <1> imap2: ; 1:
  3829                              <1> 	add	bx, [esi] ;; add free map size to si
  3830                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3831                              <1> 	add	bx, 4
  3832                              <1> 	add	ebx, esi
  3833                              <1>         	; add (sp)+,r2 / ?
  3834                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3835                              <1> 		      ;; (2 + free map size + 2)
  3836                              <1> 		; add $2,r2 / ?
  3837                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3838                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3839                              <1> 	retn
  3840                              <1> 		; rts r0
  3841                              <1> %endif
  3842                              <1> 
  3843                              <1> 	; Retro UNIX 386 v2.0 'itrunc' code
  3844                              <1> itrunc:
  3845                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  3846                              <1> 	; 07/06/2020
  3847                              <1> 	; 02/06/2020
  3848                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3849                              <1> 	;
  3850                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3851                              <1> 	;  to zero length.
  3852                              <1> 	; 07/06/2020
  3853                              <1> 	; 02/06/2020
  3854                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3855                              <1> 	;
  3856                              <1> 	; 'itrunc' truncates a file whose i-number is given
  3857                              <1> 	; in ax to zero length.
  3858                              <1> 	;
  3859                              <1> 
  3860                              <1> 	; Reference: 
  3861                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  3862                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'itrunc' procedure
  3863                              <1> 
  3864                              <1> 	; * Free all the disk blocks associated
  3865                              <1> 	; * with the specified inode structure.
  3866                              <1> 	
  3867                              <1> 	; INPUT: 
  3868                              <1> 	;	ax = inode number
  3869                              <1> 	; OUTPUT: 
  3870                              <1> 	;	inode will be modified (file size = 0)
  3871                              <1> 
  3872                              <1> 	; (Modified registers: eax, edx, ecx, ebx, esi, edi, ebp) 
  3873                              <1> 
  3874                              <1> 	; 07/06/2020
  3875                              <1> 
  3876                              <1> 	; [cdev] = current logical drive number
  3877                              <1> 	;    eax = inode number (for [cdev])
  3878                              <1> 
  3879 000055ED E812FEFFFF          <1> 	call 	iget
  3880                              <1> 	; 10/01/2022
  3881                              <1> 	;jc	short itrunc_0 ; error code in eax (al)
  3882                              <1> 
  3883                              <1> 	;    eax = inode number, [ii]
  3884                              <1> 	; [cdev] = current logical drive number (same with input)
  3885                              <1> 	; [idev] = logical drive number of current inode, [ii]
  3886                              <1> 	;   [ii] = current inode ([ii] = ax input, if ax was not zero)
  3887                              <1> 	; [imod] = 0		
  3888                              <1> 	; ([imodx] = 0)
  3889                              <1> 
  3890 000055F2 F605[45700000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file or directory	
  3891 000055F9 750F                <1> 	jnz	short itrunc_1
  3892                              <1> 
  3893                              <1> 	; 10/01/2022
  3894 000055FB C705[1C750000]FF00- <1> 	mov	dword [u.error], ERR_NOT_REGULAR ; 255 
  3894 00005603 0000                <1>
  3895                              <1> 			; 'not a regular file (or directory) !' error
  3896                              <1> itrunc_0:
  3897 00005605 E9C4E4FFFF          <1> 	jmp	error
  3898                              <1> itrunc_1:
  3899 0000560A F605[45700000]10    <1> 	test	byte [i.flgs+1], 10h ; large file (indirect blocks)
  3900 00005611 7528                <1> 	jnz	short itrunc_5 ; large file
  3901 00005613 BE[50700000]        <1> 	mov	esi, i.dskp ; disk address pointer 0
  3902                              <1> itrunc_2:
  3903 00005618 AD                  <1> 	lodsd
  3904 00005619 21C0                <1> 	and	eax, eax
  3905 0000561B 740C                <1> 	jz	short itrunc_3 ; empty ! (no more sectors/blocks)
  3906                              <1> 	; eax = block address to be released
  3907 0000561D 56                  <1> 	push	esi ; * ; 10/01/2022
  3908 0000561E E831FDFFFF          <1> 	call	free
  3909                              <1> 	; modified registers: ebx, ecx, edx, esi, edi, ebp 
  3910                              <1> 	; 10/01/2022
  3911                              <1> 	;jc	short itrunc_0 ; error code in eax
  3912 00005623 5E                  <1> 	pop	esi ; * ; 10/01/2022
  3913 00005624 31C0                <1> 	xor	eax, eax ; 0
  3914 00005626 8946FC              <1> 	mov	[esi-4], eax ; 0
  3915                              <1> itrunc_3:
  3916 00005629 81FE[78700000]      <1> 	cmp	esi, i.dskp+40
  3917 0000562F 72E7                <1> 	jb	short itrunc_2 ; next disk address ptr
  3918                              <1> itrunc_4:
  3919 00005631 A3[4C700000]        <1> 	mov	[i.size], eax ; 0
  3920                              <1> 	;mov	[i.size_h], al ; 0
  3921                              <1> 	
  3922                              <1> 	; clear large file flag
  3923                              <1> 	;and     byte [i.flgs+1], 0EFh ; 11101111b ; not 10h
  3924                              <1> 		
  3925                              <1> 	;call	setimod
  3926                              <1> 	;retn
  3927 00005636 E968FFFFFF          <1> 	jmp	setimod
  3928                              <1> 
  3929                              <1> itrunc_5:
  3930                              <1> 	; free disk blocks by using triple indirect blocks at first
  3931 0000563B BE[74700000]        <1> 	mov	esi, i.dskp+36
  3932 00005640 8B06                <1> 	mov	eax, [esi]
  3933 00005642 09C0                <1> 	or	eax, eax
  3934 00005644 740C                <1> 	jz	short itrunc_6
  3935                              <1> 
  3936 00005646 BA02000000          <1> 	mov	edx, 2 ; Triple indirect sign (level = 2)
  3937 0000564B E835000000          <1> 	call	tloop
  3938                              <1> 	; 10/01/2022
  3939                              <1> 	;jc	short itrunc_0
  3940                              <1> 		; eax = 0	
  3941 00005650 8906                <1> 	mov	[esi], eax ; 0
  3942                              <1> itrunc_6:
  3943                              <1> 	; free disk blocks by using double indirect blocks at second
  3944 00005652 BE[70700000]        <1> 	mov	esi, i.dskp+32
  3945 00005657 8B06                <1> 	mov	eax, [esi]
  3946 00005659 21C0                <1> 	and	eax, eax 
  3947 0000565B 740C                <1> 	jz	short itrunc_7
  3948                              <1> 
  3949 0000565D BA01000000          <1> 	mov	edx, 1 ; Double indirect sign (level = 1)
  3950 00005662 E81E000000          <1> 	call	tloop
  3951                              <1> 	; 10/01/2022
  3952                              <1> 	;jc	short itrunc_0
  3953                              <1> 		; eax = 0	
  3954 00005667 8906                <1> 	mov	[esi], eax ; 0
  3955                              <1> 	;esi = i.dskp+32
  3956                              <1> itrunc_7:
  3957                              <1> 	; free disk blocks by using single indirect blocks at third
  3958 00005669 83EE04              <1> 	sub	esi, 4
  3959 0000566C 8B06                <1> 	mov	eax, [esi]
  3960 0000566E 09C0                <1> 	or	eax, eax
  3961 00005670 7409                <1> 	jz	short itrunc_8
  3962                              <1> 
  3963 00005672 29D2                <1> 	sub	edx, edx ; 0  ; Single indirect sign (level = 0)
  3964 00005674 E80C000000          <1> 	call	tloop
  3965                              <1> 	; 10/01/2022
  3966                              <1> 	;jc	short itrunc_0
  3967                              <1> 		; eax = 0
  3968 00005679 8906                <1> 	mov	[esi], eax ; 0
  3969                              <1> itrunc_8:
  3970 0000567B 81FE[50700000]      <1> 	cmp	esi, i.dskp
  3971 00005681 77E6                <1> 	ja	short itrunc_7
  3972 00005683 EBAC                <1> 	jmp	short itrunc_4
  3973                              <1> 
  3974                              <1> tloop:
  3975                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  3976                              <1> 	; 07/06/2020
  3977                              <1> 	; 03/06/2020
  3978                              <1> 	; 02/06/2020
  3979                              <1> 	; 26/05/2020 - Retro UNIX 386 v2 by Erdogan Tan
  3980                              <1> 	; 
  3981                              <1> 	; * Free all the disk blocks associated
  3982                              <1> 	; * with the specified inode structure.
  3983                              <1> 
  3984                              <1> 	; Reference: 
  3985                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  3986                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'tloop' procedure
  3987                              <1> 
  3988                              <1> 	; INPUT: 
  3989                              <1> 	;	03/06/2020
  3990                              <1> 	;	eax = indirect block number/address (logical)
  3991                              <1> 	;	edx = level (in dl) 
  3992                              <1> 	;	(0 = indirect, 1 = double indr. 2 = triple indr.) 	
  3993                              <1> 	;
  3994                              <1> 	; OUTPUT: 
  3995                              <1> 	;	indirect blocks will be released
  3996                              <1> 	;
  3997                              <1> 	; Modified registers: eax, ebx, ecx, edx
  3998                              <1> 
  3999                              <1> 	; 03/06/2020
  4000                              <1> 
  4001 00005685 57                  <1> 	push	edi ; *
  4002 00005686 56                  <1> 	push	esi ; **
  4003                              <1> 
  4004 00005687 50                  <1> 	push	eax ; ***
  4005                              <1> 
  4006 00005688 52                  <1> 	push	edx ; **** level
  4007                              <1> 
  4008                              <1> 	; [ii] = current inode number
  4009                              <1> 	; [idev] = logical drive number of current inode, [ii]
  4010                              <1> 	; eax = logical sector/block number
  4011                              <1> 
  4012                              <1> 	; 10/01/2022
  4013                              <1> 	; convert to physical sector/block number/address
  4014 00005689 E845FAFFFF          <1> 	call	mget_2	
  4015                              <1> 
  4016 0000568E E8760A0000          <1> 	call	dskrd ; read disk sector
  4017                              <1> 
  4018                              <1> 		;; ebx = buffer header address
  4019                              <1> 		;; eax = physical sector/block number 
  4020                              <1> 		;; [pdn] = phsysical drive (index) number
  4021                              <1> 		
  4022                              <1> 		;; Modified registers: eax, edx, ecx, esi, edi
  4023                              <1> 		;; If cf = 1 --> eax = error code (al)
  4024                              <1> 
  4025                              <1> 	; 10/01/2022
  4026                              <1> 	; Return from 'dskrd': (Retro UNIX 386 v1.2)
  4027                              <1> 	; 	eax = physical block/sector number
  4028                              <1> 	; 	ebx = buffer data address
  4029                              <1>  	; Modified registers: edx, ecx, ebx, esi, edi, ebp
  4030                              <1>  
  4031 00005693 5A                  <1> 	pop	edx ; **** ; level in dl
  4032                              <1> 	; 10/01/2022
  4033                              <1> 	;jc	short tloop_5
  4034                              <1> 
  4035                              <1> 	;mov	esi, [ebx+bufhdr.address] ; buffer address
  4036                              <1> 	; 10/01/2022
  4037 00005694 89DE                <1> 	mov	esi, ebx ; buffer data address	
  4038                              <1> 
  4039                              <1> 	; 07/06/2020
  4040 00005696 B980000000          <1> 	mov	ecx, 512/4 ; 128 dwords	
  4041                              <1> 
  4042 0000569B 80FA01              <1> 	cmp	dl, 1 ; -
  4043 0000569E 722A                <1> 	jb	short tloop_7
  4044 000056A0 7407                <1> 	je	short tloop_1
  4045 000056A2 BF[5C7B0000]        <1> 	mov	edi, trpi_buf ; triple indirect buffer address
  4046 000056A7 EB05                <1> 	jmp	short tloop_2
  4047                              <1> tloop_1:
  4048 000056A9 BF[5C790000]        <1> 	mov	edi, dbli_buf ; double indirect buffer address
  4049                              <1> tloop_2:
  4050                              <1> 	; copy disk r/w buffer content to indirect block buffer
  4051                              <1> 	;mov	ecx, 512/4 ; 128 dwords	
  4052 000056AE F3A5                <1> 	rep	movsd
  4053                              <1> 
  4054 000056B0 FECA                <1> 	dec	dl ; -
  4055                              <1> 		   ; next indirect block level, 2 -> 1, 1 -> 0
  4056 000056B2 89FE                <1> 	mov	esi, edi  ; (dbli, trpi) indirect buffer + 512
  4057 000056B4 B180                <1> 	mov	cl, 128 ; 128 dwords
  4058                              <1> tloop_3:
  4059 000056B6 83EE04              <1> 	sub	esi, 4  ; previous pointer
  4060                              <1> 
  4061 000056B9 8B06                <1> 	mov	eax, [esi]
  4062                              <1> 
  4063 000056BB 09C0                <1> 	or	eax, eax ; 0
  4064 000056BD 7407                <1> 	jz	short tloop_4
  4065                              <1> 
  4066                              <1> 	; 03/06/2020
  4067 000056BF 51                  <1> 	push	ecx ; @
  4068 000056C0 E8C0FFFFFF          <1> 	call	tloop
  4069 000056C5 59                  <1> 	pop	ecx ; @
  4070                              <1> 	; 10/01/2022
  4071                              <1> 	;jc	short tloop_5
  4072                              <1> tloop_4:
  4073 000056C6 E2EE                <1> 	loop	tloop_3
  4074                              <1> 
  4075 000056C8 EB1A                <1> 	jmp	short tloop_10
  4076                              <1> 
  4077                              <1> 	; 10/01/2022
  4078                              <1> ;tloop_5:
  4079                              <1> ;	pop	edx ; ***  ; discard eax
  4080                              <1> ;	; error code in eax
  4081                              <1> ;tloop_6:
  4082                              <1> ;	pop	esi ; **
  4083                              <1> ;	pop	edi ; *
  4084                              <1> ;	retn
  4085                              <1> 	
  4086                              <1> 	; free blocks in current indirect block
  4087                              <1> tloop_7:
  4088                              <1> 	;mov	ecx, 512/4  ; 128 dwords
  4089 000056CA 81C6FC010000        <1> 	add	esi, 508
  4090                              <1> tloop_8:
  4091 000056D0 8B06                <1> 	mov	eax, [esi]
  4092 000056D2 21C0                <1> 	and	eax, eax ; 0 ?
  4093 000056D4 7409                <1> 	jz	short tloop_9
  4094                              <1> 	
  4095 000056D6 56                  <1> 	push	esi ; **** ; 10/01/2022
  4096 000056D7 51                  <1> 	push	ecx ; *****
  4097 000056D8 E877FCFFFF          <1> 	call	free
  4098                              <1> 		; if cf = 0 -> eax = 0
  4099                              <1> 		; if cf = 1 -> eax = error code (in al)
  4100 000056DD 59                  <1> 	pop	ecx ; *****
  4101 000056DE 5E                  <1> 	pop	esi ; **** ; 10/01/2022
  4102                              <1> 	; 10/01/2022
  4103                              <1> 	;; 07/06/2020
  4104                              <1> 	;jc	short tloop_6
  4105                              <1> tloop_9:
  4106 000056DF 83EE04              <1> 	sub	esi, 4
  4107 000056E2 E2EC                <1> 	loop	tloop_8
  4108                              <1> tloop_10:
  4109 000056E4 58                  <1> 	pop	eax ; *** ; free indirect block's itself
  4110 000056E5 E86AFCFFFF          <1> 	call	free
  4111                              <1> 		;; if cf = 0 -> eax = 0
  4112                              <1> 		;; if cf = 1 -> eax = error code (in al)
  4113                              <1> 	; 10/01/2022
  4114                              <1> 	; (if we are here, there is not an error, cf=0) 
  4115                              <1> 	;jmp	short tloop_6
  4116                              <1> 
  4117                              <1> 	; 10/02/2022
  4118 000056EA 31C0                <1> 	xor	eax, eax ; 0
  4119 000056EC 5E                  <1> 	pop	esi ; **
  4120 000056ED 5F                  <1> 	pop	edi ; *
  4121 000056EE C3                  <1> 	retn
  4122                              <1> 
  4123                              <1> 	; Retro UNIX 386 v2.0 'imap' code
  4124                              <1> 	;	(runix v2 fs inode map)
  4125                              <1> imap:
  4126                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  4127                              <1> 	;	(major modification)
  4128                              <1> 	; 05/11/2021 - temporary (simplified code)
  4129                              <1> 	; 21/08/2021
  4130                              <1> 	; 15/08/2021
  4131                              <1> 	; 14/06/2021
  4132                              <1> 	; 02/05/2021
  4133                              <1> 	; 01/04/2021, 08/04/2021, 24/04/2021
  4134                              <1> 	; 29/03/2021
  4135                              <1> 	; 28/03/2021 - Retro UNIX 386 v2 (beginning)
  4136                              <1> 	;
  4137                              <1> 	; 'imap' finds the byte in inode map containing
  4138                              <1> 	; allocation bit for an i-node whose number in (E)AX
  4139                              <1> 	;
  4140                              <1> 	; (ref: 'UNIXHDCP.ASM', imap', 22/01/2020) 
  4141                              <1> 	;
  4142                              <1> 	; ((Retro UNIX 386 v2 'imap' code is mostly different
  4143                              <1> 	; than Retro UNIX 386 v1.1 'imap' code.))
  4144                              <1> 	;
  4145                              <1> 	; INPUTS ->
  4146                              <1> 	;   EAX = inode number
  4147                              <1> 	;        0 = first free inode
  4148                              <1> 	;       >0 = requested inode
  4149                              <1> 	;   [cdev] = current (logical) drive/device
  4150                              <1> 	;	
  4151                              <1> 	; OUTPUTS ->
  4152                              <1> 	;    EBX = address of the byte contains allocation bit
  4153                              <1> 	;     DX has 1 at calculated bit position
  4154                              <1> 	;   ; 05/11/2021	
  4155                              <1> 	;    EBP = superblock buffer address  
  4156                              <1> 	;    (EAX = inode number)	  	
  4157                              <1> 	;   ; 08/04/2021
  4158                              <1> 	;     If cf=1 -> error code in eax (al) 	
  4159                              <1> 	;
  4160                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp
  4161                              <1> 
  4162                              <1> 	; 05/11/2021
  4163 000056EF 803D[89740000]00    <1> 	cmp	byte [cdev], 0
  4164 000056F6 7616                <1> 	jna	short imap_0
  4165                              <1> 	; 10/01/2022
  4166 000056F8 BD[5C770000]        <1> 	mov	ebp, mount ; mounted fs superblock buffer
  4167 000056FD EB14                <1> 	jmp	short imap_1
  4168                              <1> 
  4169                              <1> imap_ialloc_err:
  4170                              <1> 	; 10/01/2022
  4171 000056FF C705[1C750000]2100- <1> 	mov	dword [u.error], ERR_INO_ALLOC ; 33
  4171 00005707 0000                <1>
  4172                              <1> 			; 'inode allocation error !'
  4173 00005709 E9C0E3FFFF          <1> 	jmp	error
  4174                              <1>  
  4175                              <1> imap_0:
  4176                              <1> 	; 10/01/2022
  4177 0000570E BD[54750000]        <1> 	mov	ebp, systm ; root fs superblock buffer
  4178                              <1> imap_1:
  4179                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4180                              <1> imap_x:
  4181                              <1> 	; 05/11/2021
  4182                              <1> 	; 21/08/2021
  4183                              <1> 	; 15/08/2021 (Retro UNIX 386 v2)
  4184                              <1> 	; call from 'maknod2' ; 10/01/2022
  4185                              <1> 	;
  4186                              <1> 	; eax = inode number
  4187                              <1> 	; [cdev] = device number for inode in eax
  4188                              <1> 	; ebp = superblock buffer address
  4189                              <1> 
  4190                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4191                              <1> 	; 'imap' and 'imap_x' will return with..
  4192                              <1> 	;    ECX = byte offset from inode map buff (imap_x)
  4193                              <1> 	;    EBX = byte addr of the byte with allocation bit
  4194                              <1> 	;    EDX (DL) has a 1 in the calculated bit position
  4195                              <1> 
  4196                              <1> 	; 02/05/2021
  4197                              <1> 	; convert inode number to first free inode if it is 0
  4198 00005713 E83D000000          <1> 	call	imap_3 ; 10/01/2022
  4199 00005718 72E5                <1> 	jc	short imap_ialloc_err
  4200                              <1> 	; eax = inode number > 1 (1 = root directory inode)
  4201                              <1> 
  4202 0000571A 898584000000        <1> 	mov	[ebp+SB.LastInode], eax
  4203                              <1> 	
  4204 00005720 50                  <1> 	push	eax ; * ; save inode number
  4205                              <1> 
  4206                              <1> 	; convert inode number to inode map sector index
  4207 00005721 E847000000          <1> 	call	imap_8 ; 10/01/2022
  4208 00005726 50                  <1> 	push	eax ; ** ; byte offset in inode map buffer
  4209                              <1> 
  4210                              <1> 	; edx = inode map buffer sector index number (< 16)
  4211                              <1> 	; eax = byte offset in inode map buffer (< 512)
  4212                              <1> 
  4213                              <1> 	; 15/08/2021
  4214 00005727 89958C000000        <1> 	mov	[ebp+SB.ImapIndex], edx
  4215 0000572D 8B4520              <1> 	mov	eax, [ebp+SB.InodeMapAddr]
  4216 00005730 01D0                <1> 	add	eax, edx
  4217 00005732 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  4218                              <1> 	; eax = physical sector number
  4219                              <1> 	; [cdev] = current device/disk number
  4220                              <1> 	
  4221                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4222 00005735 55                  <1> 	push	ebp ; ***
  4223 00005736 E8CE090000          <1> 	call	dskrd
  4224 0000573B 5D                  <1> 	pop	ebp ; ***
  4225                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  4226                              <1> 	; eax = physical sector number
  4227                              <1> 	; ebx = buffer data address
  4228                              <1> 
  4229                              <1> 	; 10/01/2022
  4230 0000573C 8A4C2404            <1> 	mov	cl, [esp+4] ; * ; inode number
  4231                              <1> 	;dec	cl
  4232 00005740 31D2                <1> 	xor	edx, edx
  4233                              <1> 	;mov	dl, 1
  4234 00005742 FEC2                <1> 	inc	dl ; dl = 1
  4235                              <1> 	;and	ecx, 7
  4236                              <1> 	; 02/05/2021
  4237 00005744 FEC9                <1> 	dec	cl
  4238 00005746 7405                <1> 	jz	short imap_2 ; 15/08/2021
  4239 00005748 80E107              <1> 	and	cl, 7	; 1 imap bytes is for 8 inodes 
  4240 0000574B D2E2                <1> 	shl	dl, cl
  4241                              <1> imap_2:
  4242                              <1> 	; 10/01/2022
  4243                              <1> 	; save physical sector number of imap sector in the SB
  4244 0000574D 89457C              <1> 	mov	[ebp+SB.ImapBuffer], eax ; ! sector addr !
  4245                              <1> 	; 
  4246 00005750 59                  <1> 	pop	ecx ; ** ; byte offset in inode map buffer
  4247 00005751 01CB                <1> 	add	ebx, ecx ; + byte position
  4248 00005753 58                  <1> 	pop	eax ; * ; inode number
  4249                              <1> 
  4250                              <1> 	; 10/01/2022
  4251                              <1> 	; ECX contains byte offset from inode map buff (imap_x)
  4252                              <1> 	; EDX (DL) has a 1 in the calculated bit position
  4253                              <1> 	; EBX has byte address of the byte with allocation bit
  4254                              <1> 
  4255 00005754 C3                  <1> 	retn
  4256                              <1> 
  4257                              <1> imap_3:
  4258                              <1> 	; 10/01/2022
  4259                              <1> 	; 15/08/2021
  4260                              <1> 	; 02/05/2021
  4261                              <1> 	; 28/03/2021
  4262                              <1> 	; get first free inode number (from superblock)
  4263                              <1> 	; and check inode number against inode count
  4264                              <1> 	;
  4265                              <1> 	; INPUT:
  4266                              <1> 	;    eax = 0 -> get first free inode number
  4267                              <1> 	;    (eax > 0 -> check inode number)
  4268                              <1> 	;    ebp = superblock address ; 15/08/2021
  4269                              <1> 	; OUTPUT:
  4270                              <1> 	;    eax = inode number 
  4271                              <1> 	;    (eax will be 2 when SB.FirstFreeIno is invalid)
  4272                              <1> 	;    cf = 1 -> inode allocation error/problem
  4273                              <1> 	
  4274 00005755 21C0                <1> 	and	eax, eax	
  4275 00005757 750E                <1> 	jnz	short imap_5
  4276                              <1> 
  4277                              <1> 	; get first free inode
  4278                              <1> 	;mov	eax, [ebp+SB.FreeInodes]
  4279                              <1> 	;and	eax, eax
  4280                              <1> 	;jz	short imap_6
  4281                              <1> 	; 10/01/2022
  4282 00005759 394530              <1> 	cmp	[ebp+SB.FreeInodes], eax ; 0
  4283 0000575C 760D                <1> 	jna	short imap_6	
  4284 0000575E 8B4534              <1> 	mov	eax, [ebp+SB.FirstFreeIno] ; 1 based inode num
  4285 00005761 40                  <1> 	inc	eax
  4286 00005762 7502                <1> 	jnz	short imap_4 ; 0FFFFFFFFh -> 0
  4287                              <1> 	; invalid first free inode value (not initialized)
  4288 00005764 B003                <1> 	mov	al, 3 ; first free inode to be searched + 1
  4289                              <1> imap_4:
  4290 00005766 48                  <1> 	dec	eax
  4291                              <1> imap_5:
  4292                              <1> 	; 15/08/2021
  4293                              <1> 	; check inode number against inode count of the fs
  4294 00005767 394514              <1> 	cmp	[ebp+SB.InodeCount], eax
  4295 0000576A C3                  <1> 	retn	; if cf = 1 --> inode number > inode count
  4296                              <1> imap_6:
  4297                              <1> 	; 'imap' inode allocation error !
  4298 0000576B F9                  <1> 	stc
  4299                              <1> imap_7:
  4300 0000576C C3                  <1> 	retn
  4301                              <1> 
  4302                              <1> imap_8:
  4303                              <1> 	; 10/01/2022
  4304                              <1> 	; 15/08/2021
  4305                              <1> 	; 02/05/2021
  4306                              <1> 	; 28/03/2021
  4307                              <1> 	; convert inode count to inode map sector index
  4308                              <1> 	;
  4309                              <1> 	; INPUT: 
  4310                              <1> 	;    eax = inode number
  4311                              <1> 	; OUTPUT:
  4312                              <1> 	;    edx = inode map sector offset/index number
  4313                              <1> 	;    eax = byte offset from start of imapbuf	 
  4314                              <1> 
  4315 0000576D 31D2                <1> 	xor	edx, edx
  4316 0000576F 48                  <1> 	dec	eax ; zero based inode number
  4317 00005770 74FA                <1> 	jz	short imap_7
  4318                              <1> 
  4319 00005772 C1E803              <1> 	shr	eax, 3 ; 8 inodes per inode map byte
  4320                              <1> 		; eax = byte offset from start of inode map
  4321 00005775 88E2                <1> 	mov	dl, ah ; ah <= 31 (1Fh) for Retro UNIX 386 v2
  4322 00005777 D0EA                <1> 	shr	dl, 1
  4323                              <1> 		; edx = inode map sector offset/index number
  4324                              <1> 	;and	eax, 511
  4325 00005779 6625FF01            <1> 	and	ax, 511
  4326                              <1> 		; eax = byte offset from start of imapbuf
  4327 0000577D C3                  <1> 	retn
  2077                                  %include 'u6.s'      ; 31/05/2015
  2078                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2079                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2080                              <1> ; ****************************************************************************
  2081                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC
  2082                              <1> ; Last Modification: 11/01/2022
  2083                              <1> ; ----------------------------------------------------------------------------
  2084                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2085                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2086                              <1> ;
  2087                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2088                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2089                              <1> ; <Bell Laboratories (17/3/1972)>
  2090                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2091                              <1> ;
  2092                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2093                              <1> ;
  2094                              <1> ; ****************************************************************************
  2095                              <1> 
  2096                              <1> 	; 25/12/2021
  2097                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2098                              <1> readi:
  2099                              <1> 	; 20/05/2015
  2100                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2101                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2102                              <1> 	;
  2103                              <1> 	; Reads from an inode whose number in R1
  2104                              <1> 	; 
  2105                              <1> 	; INPUTS ->
  2106                              <1> 	;    r1 - inode number
  2107                              <1> 	;    u.count - byte count user desires
  2108                              <1> 	;    u.base - points to user buffer
  2109                              <1> 	;    u.fofp - points to word with current file offset
  2110                              <1> 	; OUTPUTS ->
  2111                              <1> 	;    u.count - cleared
  2112                              <1> 	;    u.nread - accumulates total bytes passed back
  2113                              <1> 	;
  2114                              <1> 	; ((AX = R1)) input/output
  2115                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2116                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2117                              <1> 
  2118 0000577E 31D2                <1> 	xor	edx, edx ; 0
  2119 00005780 8915[D4740000]      <1> 	mov 	[u.nread], edx ; 0
  2120                              <1> 		; clr u.nread / accumulates number of bytes transmitted
  2121 00005786 668915[14750000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2122 0000578D 3915[D0740000]      <1> 	cmp 	[u.count], edx ; 0
  2123                              <1> 		; tst u.count / is number of bytes to be read greater than 0
  2124 00005793 7701                <1> 	ja 	short readi_1 ; 1f
  2125                              <1> 		; bgt 1f / yes, branch
  2126 00005795 C3                  <1> 	retn
  2127                              <1> 		; rts r0 / no, nothing to read; return to caller
  2128                              <1> readi_1: ; 1:
  2129                              <1> 	;	; mov r1,-(sp) / save i-number on stack
  2130                              <1> 	;cmp	ax, 40
  2131                              <1> 	;	; cmp r1,$40. / want to read a special file 
  2132                              <1> 	;	;             / (i-nodes 1,...,40 are for special files)
  2133                              <1>         ;ja	dskr 
  2134                              <1> 	;	; ble 1f / yes, branch
  2135                              <1> 	;	; jmp dskr / no, jmp to dskr; 
  2136                              <1> 	;	;         / read file with i-node number (r1)
  2137                              <1> 	;	;    / starting at byte ((u.fofp)), read in u.count bytes
  2138                              <1> 	
  2139                              <1> 	; 28/11/2021
  2140 00005796 F605[1A750000]FF    <1> 	test	byte [u.kcall], 0FFh
  2141 0000579D 7505                <1> 	jnz	short readi_2  ; 'readi' called by 'namei'
  2142                              <1> 
  2143                              <1> 	; eax = inode number
  2144                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2145 0000579F E860FCFFFF          <1> 	call	iget
  2146                              <1> readi_2:
  2147                              <1> 	; 28/11/2021
  2148                              <1> 	; eax = inode number
  2149                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2150 000057A4 E881040000          <1> 	call	is_regular_file
  2151                              <1> 	;jz	dskr ; regular file 
  2152                              <1> 	; 25/12/2021
  2153 000057A9 7505                <1> 	jnz	short readi_5 ; device file 
  2154                              <1> 	; regular file
  2155 000057AB E9E3000000          <1> 	jmp	dskr
  2156                              <1> readi_5:
  2157                              <1> 	; (20/05/2015)
  2158 000057B0 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2159                              <1> 
  2160                              <1> 	; 28/11/2021	
  2161                              <1> 	; device file
  2162 000057B1 BB[CB570000]        <1> 	mov	ebx, readi_4
  2163 000057B6 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2164 000057B9 720E                <1> 	jb	short readi_3
  2165 000057BB 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2166 000057BE 7709                <1> 	ja	short readi_3	
  2167                              <1> 	
  2168                              <1> 	; convert v2 inode number to v1 device inode number
  2169 000057C0 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2170 000057C2 89C1                <1> 	mov	ecx, eax
  2171 000057C4 C0E102              <1> 	shl	cl, 2 ; * 4
  2172 000057C7 01CB                <1> 	add	ebx, ecx
  2173                              <1> readi_3:
  2174 000057C9 FF23                <1> 	jmp	dword [ebx]	
  2175                              <1> 		 ; jmp *1f-2(r1)
  2176                              <1> readi_4: ; 1:
  2177 000057CB [1B580000]          <1> 	dd	null ; 28/11/2021
  2178 000057CF [1F580000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2179                              <1> 		 ;rtty / tty; r1=2
  2180                              <1> 		 ;rppt / ppt; r1=4
  2181 000057D3 [6F580000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2182                              <1> 		 ;rmem / mem; r1=6
  2183                              <1> 		 ;rrf0 / rf0
  2184                              <1> 		 ;rrk0 / rk0
  2185                              <1> 		 ;rtap / tap0
  2186                              <1> 		 ;rtap / tap1
  2187                              <1> 		 ;rtap / tap2
  2188                              <1> 		 ;rtap / tap3
  2189                              <1> 		 ;rtap / tap4
  2190                              <1> 		 ;rtap / tap5
  2191                              <1> 		 ;rtap / tap6
  2192                              <1> 		 ;rtap / tap7
  2193 000057D7 [BA5F0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2194 000057DB [BA5F0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2195 000057DF [BA5F0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2196 000057E3 [BA5F0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2197 000057E7 [BA5F0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2198 000057EB [BA5F0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2199 000057EF [84580000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2200 000057F3 [6B580000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2201                              <1> 		 ;rcvt / tty0
  2202 000057F7 [6B580000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2203                              <1> 		 ;rcvt / tty1
  2204 000057FB [6B580000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2205                              <1> 		 ;rcvt / tty2
  2206 000057FF [6B580000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2207                              <1> 		 ;rcvt / tty3
  2208 00005803 [6B580000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2209                              <1> 		 ;rcvt / tty4
  2210 00005807 [6B580000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2211                              <1> 		 ;rcvt / tty5
  2212 0000580B [6B580000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2213                              <1> 		 ;rcvt / tty6
  2214 0000580F [6B580000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2215                              <1> 		 ;rcvt / tty7
  2216 00005813 [6B580000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2217                              <1> 		 ;rcrd / crd
  2218 00005817 [6B580000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2219                              <1> 
  2220                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2221                              <1> null:
  2222 0000581B 31C0                <1> 	xor	eax, eax
  2223 0000581D 58                  <1> 	pop	eax
  2224 0000581E C3                  <1> 	retn
  2225                              <1> 
  2226                              <1> 	; 11/01/2022
  2227                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2228                              <1> rtty: ; / read from console tty
  2229                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2230                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2231                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2232                              <1> 	;	     must be written immediate on video page (screen)
  2233                              <1> 	;	     when it is required.	
  2234                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2235                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2236                              <1> 	;
  2237                              <1> 	; Console tty buffer is PC keyboard buffer
  2238                              <1> 	; and keyboard-keystroke handling is different than original
  2239                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2240                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2241                              <1> 	;
  2242                              <1> 	; 06/12/2013
  2243 0000581F 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2244 00005826 8A83[C3700000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2245                              <1> rttys:
  2246                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2247                              <1> 	               ; / of the control and status block
  2248                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2249                              <1> 		       ; / tty buffer
  2250                              <1> 	; 28/07/2013
  2251 0000582C A2[DD740000]        <1> 	mov 	[u.ttyn], al
  2252                              <1> 	; 13/01/2014
  2253 00005831 FEC0                <1> 	inc	al
  2254 00005833 A2[DE740000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2255                              <1> rtty_nc: ; 01/02/2014
  2256                              <1> 	; 29/09/2013
  2257                              <1> 	;mov	ecx, 10
  2258                              <1> 	; 11/01/2022
  2259 00005838 29C9                <1> 	sub	ecx, ecx
  2260 0000583A B10A                <1> 	mov	cl, 10
  2261                              <1> rtty_1: 	; 01/02/2014
  2262                              <1> 	;push 	cx ; 29/09/2013
  2263                              <1> 	; 11/12/2021
  2264 0000583C 51                  <1> 	push	ecx
  2265                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2266 0000583D B001                <1> 	mov 	al, 1
  2267 0000583F E8CD0B0000          <1> 	call 	getc
  2268                              <1> 	;pop 	cx ; 29/09/2013	
  2269                              <1> 	; 11/12/2021
  2270 00005844 59                  <1> 	pop	ecx
  2271 00005845 7516                <1> 	jnz	short rtty_2
  2272                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2273                              <1> 	               ; / of chars. Is this number non-zero?
  2274 00005847 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2275                              <1> 	; 05/10/2013
  2276 00005849 8A25[DD740000]      <1> 	mov	ah, [u.ttyn]
  2277                              <1> 	; 29/09/2013
  2278 0000584F E8AEF7FFFF          <1> 	call	sleep
  2279                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2280                              <1>                 ;           / (120 chars.)
  2281                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2282 00005854 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2283                              <1> 
  2284                              <1> rtty_idle:
  2285                              <1> 	; 29/07/2013
  2286 00005856 E814F7FFFF          <1> 	call 	idle
  2287 0000585B EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2288                              <1> 	;1:
  2289                              <1> 		; tst 2(r5) / is the number of characters zero
  2290                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2291                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2292                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2293                              <1> 		          ; / contains the next char.
  2294                              <1> 		; dec 2(r5) / decrement the character count
  2295                              <1> rtty_2:
  2296 0000585D 30C0                <1> 	xor 	al, al
  2297 0000585F E8AD0B0000          <1> 	call 	getc
  2298 00005864 E891000000          <1> 	call	passc
  2299                              <1> 		; jsr r0,passc / move the character to core (user)
  2300                              <1> 	;; 17/10/2015 - 16/07/2015
  2301                              <1> 	; 19/06/2014
  2302                              <1> 	;;jnz	short rtty_nc
  2303 00005869 58                  <1> 	pop	eax  ; (20/05/2015)
  2304 0000586A C3                  <1> 	retn 
  2305                              <1> ;ret1:
  2306                              <1> 		; jmp ret / return to caller via 'ret'
  2307                              <1> 
  2308                              <1> rcvt:   ; < receive/read character from tty >
  2309                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2310                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2311                              <1> 	;
  2312                              <1> 	; Retro UNIX 8086 v1 modification !
  2313                              <1> 	; 
  2314                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2315                              <1> 	;		(exactly different than this one)
  2316                              <1> 	;	was in 'u9.s' file.
  2317                              <1> 	;
  2318 0000586B 2C0A                <1> 	sub 	al, 10
  2319                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2320                              <1> 	; 16/07/2013
  2321                              <1> 	; 21/05/2013
  2322 0000586D EBBD                <1>         jmp     short rttys
  2323                              <1>       
  2324                              <1> ;rppt: / read paper tape
  2325                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2326                              <1> ;			 / places
  2327                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2328                              <1> ;		       / also enables read bit in prs
  2329                              <1> ;	jsr	r0,passc / place character in users buffer area
  2330                              <1> ;	br	rppt
  2331                              <1> 
  2332                              <1> rmem: ; / transfer characters from memory to a user area of core
  2333                              <1> 	; 17/10/2015
  2334                              <1> 	; 11/06/2015
  2335                              <1> 	; 24/05/2015
  2336                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2337                              <1> 	;
  2338 0000586F 8B35[BC740000]      <1> 	mov     esi, [u.fofp]
  2339                              <1> rmem_1:
  2340 00005875 8B1E                <1>         mov     ebx, [esi]        
  2341                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2342                              <1> 		               ; / to be transferred to user
  2343 00005877 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2344                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2345                              <1> 			    ; / char in memory file
  2346 00005879 8A03                <1> 	mov	al, [ebx]
  2347                              <1> 		; movb (r1),r1 / get character from memory file, 
  2348                              <1> 		             ; / put it in r1
  2349 0000587B E87A000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2350                              <1> 			     ;  / the next byte of the users core area
  2351                              <1> 		; br rmem / continue
  2352 00005880 75F3                <1> 	jnz	short rmem_1
  2353                              <1> ret_:
  2354 00005882 58                  <1> 	pop	eax ; 09/06/2015
  2355 00005883 C3                  <1> 	retn
  2356                              <1> 
  2357                              <1> rlpr:
  2358                              <1> ;1:
  2359                              <1> ;rcrd:
  2360 00005884 C705[1C750000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2360 0000588C 0000                <1>
  2361 0000588E E93BE2FFFF          <1> 	jmp	error
  2362                              <1> 		;jmp	error / see 'error' routine
  2363                              <1> 
  2364                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2365                              <1> dskr:
  2366                              <1> 	; 12/10/2015
  2367                              <1> 	; 21/08/2015
  2368                              <1> 	; 25/07/2015
  2369                              <1> 	; 10/07/2015
  2370                              <1> 	; 16/06/2015
  2371                              <1> 	; 31/05/2015
  2372                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2373                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2374                              <1> dskr_0:
  2375 00005893 50                  <1> 	push	eax
  2376                              <1> 		; mov (sp),r1 / i-number in r1
  2377                              <1> 	; AX = i-number
  2378 00005894 E86BFBFFFF          <1> 	call	iget
  2379                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2380                              <1>         ;movzx	edx, word [i.size] ; 16/06/2015
  2381                              <1> 	;	; mov i.size,r2 / file size in bytes in r2
  2382                              <1> 	; 28/11/2021
  2383 00005899 8B15[4C700000]      <1> 	mov	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2384                              <1> 	;
  2385 0000589F 8B1D[BC740000]      <1> 	mov	ebx, [u.fofp]
  2386 000058A5 2B13                <1> 	sub	edx, [ebx]
  2387                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2388                              <1>         ; 12/10/2015
  2389                              <1> 	; jna	short ret_ 
  2390                              <1> 		; blos ret
  2391 000058A7 7709                <1> 	ja	short dskr_1
  2392                              <1> 	;
  2393                              <1> dskr_retn: ; 12/10/2015
  2394 000058A9 58                  <1> 	pop	eax
  2395 000058AA C605[1A750000]00    <1> 	mov	byte [u.kcall], 0
  2396 000058B1 C3                  <1> 	retn	
  2397                              <1> dskr_1: 
  2398 000058B2 3B15[D0740000]      <1> 	cmp     edx, [u.count] 
  2399                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2400                              <1> 			       ; / to carry out read
  2401 000058B8 7306                <1> 	jnb	short dskr_2
  2402                              <1> 		; bhis 1f
  2403 000058BA 8915[D0740000]      <1> 	mov	[u.count], edx
  2404                              <1> 		; mov r2,u.count / no, just read to end of file
  2405                              <1> dskr_2: ; 1:
  2406                              <1> 	; (E)AX = i-number ; 28/11/2021 (32 bit inode number)
  2407                              <1> 	;call	mget
  2408                              <1> 		; jsr r0,mget / returns physical block number of block 
  2409                              <1> 		    ; / in file where offset points
  2410                              <1> 	; 28/11/2021
  2411 000058C0 E8C6F7FFFF          <1> 	call	mget_r
  2412                              <1> 
  2413                              <1> 	; eax = physical block number
  2414                              <1> 	; [cdev] = current device number 
  2415 000058C5 E83F080000          <1> 	call	dskrd
  2416                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2417                              <1> 			     ; / 1st word of data in buffer
  2418                              <1> 	; 09/06/2015
  2419 000058CA 803D[1A750000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2420 000058D1 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2421 000058D3 66833D[14750000]00  <1> 	cmp	word [u.pcount], 0
  2422 000058DB 7705                <1> 	ja	short dskr_4
  2423                              <1> dskr_3:
  2424                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2425 000058DD E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2426                              <1> dskr_4:
  2427                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2428 000058E2 E8C2020000          <1> 	call	sioreg
  2429                              <1> 		; jsr r0,sioreg
  2430 000058E7 87F7                <1> 	xchg	esi, edi
  2431                              <1> 	; edi = file (user data) offset
  2432                              <1> 	; edi = sector (I/O) buffer offset
  2433                              <1> 	; ecx = byte count
  2434 000058E9 F3A4                <1> 	rep	movsb
  2435                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2436                              <1> 		                 ; / starting at u.base
  2437                              <1> 		; dec r3
  2438                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2439                              <1> 	; 25/07/2015
  2440                              <1> 	; eax = remain bytes in buffer
  2441                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2442 000058EB 09C0                <1> 	or	eax, eax
  2443 000058ED 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2444                              <1> 	; 03/08/2013
  2445                              <1> 	;pop	eax
  2446 000058EF 390D[D0740000]      <1> 	cmp	[u.count], ecx ; 0
  2447                              <1> 		; tst u.count / all bytes read off disk
  2448                              <1> 		; bne dskr
  2449                              <1> 		; br ret
  2450                              <1>         ;ja	short dskr_0
  2451                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2452                              <1> 	;retn
  2453                              <1> 	; 12/10/2015
  2454 000058F5 76B2                <1> 	jna	short dskr_retn
  2455 000058F7 58                  <1> 	pop	eax  ; (i-node number)
  2456 000058F8 EB99                <1> 	jmp	short dskr_0
  2457                              <1> 	
  2458                              <1> passc:
  2459                              <1> 	; 18/10/2015
  2460                              <1> 	; 10/07/2015
  2461                              <1> 	; 01/07/2015
  2462                              <1> 	; 08/06/2015
  2463                              <1> 	; 04/06/2015
  2464                              <1> 	; 20/05/2015
  2465                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2466                              <1> 	;
  2467                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2468                              <1> 	;		      to physical address
  2469 000058FA 66833D[14750000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2470                              <1> 			     ; 1-4095 --> use previous physical base address
  2471                              <1> 			     ; in [u.pbase]
  2472 00005902 7705                <1> 	ja	short passc_3
  2473                              <1> 	; 08/06/2015 - 10/07/2015
  2474 00005904 E82C000000          <1> 	call	trans_addr_w
  2475                              <1> passc_3:
  2476                              <1> 	; 19/05/2015
  2477 00005909 66FF0D[14750000]    <1> 	dec	word [u.pcount]
  2478                              <1> 	;
  2479 00005910 8B1D[10750000]      <1> 	mov	ebx, [u.pbase]
  2480 00005916 8803                <1> 	mov	[ebx], al
  2481                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2482                              <1> 		               ; / users buffer
  2483 00005918 FF05[CC740000]      <1> 	inc	dword [u.base]
  2484                              <1> 		; inc u.base / increment the pointer to point to 
  2485                              <1> 			  ; / the next byte in users buffer
  2486 0000591E FF05[10750000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2487 00005924 FF05[D4740000]      <1> 	inc	dword [u.nread]
  2488                              <1> 		; inc u.nread / increment the number of bytes read
  2489 0000592A FF0D[D0740000]      <1> 	dec	dword [u.count]
  2490                              <1> 		; dec u.count / decrement the number of bytes to be read
  2491                              <1> 		; bne 1f / any more bytes to read? ; yes, branch
  2492 00005930 C3                  <1> 	retn
  2493                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2494                              <1> 		             ; / 'readi' by:
  2495                              <1> 		;/ (1) pop the return address off the stack into r0
  2496                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2497                              <1> 	;1:
  2498                              <1> 		; clr	*$ps / clear processor status
  2499                              <1> 		; rts r0 / return to address currently on top of stack
  2500                              <1> 
  2501                              <1> trans_addr_r:
  2502                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2503                              <1> 	;	-'add_to_swap_queue' call is disabled as temporary-
  2504                              <1> 	; Translate virtual address to physical address 
  2505                              <1> 	; for reading from user's memory space
  2506                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2507                              <1> 	; 18/10/2015
  2508                              <1> 	; 10/07/2015
  2509                              <1> 	; 09/06/2015
  2510                              <1> 	; 08/06/2015 
  2511                              <1> 	; 04/06/2015
  2512                              <1> 	;
  2513                              <1> 	; 18/10/2015
  2514 00005931 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2515 00005933 EB04                <1> 	jmp 	short trans_addr_rw
  2516                              <1> 
  2517                              <1> 	;push	eax
  2518                              <1> 	;push	ebx
  2519                              <1> 	;mov	ebx, [u.base]
  2520                              <1> 	;call	get_physical_addr ; get physical address
  2521                              <1> 	;;jnc	short cpass_0
  2522                              <1> 	;jnc	short passc_1
  2523                              <1> 	;mov	[u.error], eax
  2524                              <1> 	;;pop	ebx
  2525                              <1> 	;;pop	eax
  2526                              <1> 	;jmp	error
  2527                              <1> ;cpass_0:
  2528                              <1> 	; 18/10/2015
  2529                              <1> 	; 20/05/2015
  2530                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2531                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2532                              <1> 	;pop	ebx
  2533                              <1> 	;pop	eax
  2534                              <1> 	;retn	; 08/06/2015
  2535                              <1> 
  2536                              <1> trans_addr_w:
  2537                              <1> 	; 31/12/2021
  2538                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2539                              <1> 	;	-'add_to_swap_queue' call is disabled as temporary-
  2540                              <1> 	; Translate virtual address to physical address
  2541                              <1> 	; for writing to user's memory space
  2542                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2543                              <1> 	; 18/10/2015
  2544                              <1> 	; 29/07/2015
  2545                              <1> 	; 10/07/2015
  2546                              <1> 	; 09/06/2015
  2547                              <1> 	; 08/06/2015
  2548                              <1> 	; 04/06/2015 (passc)
  2549                              <1> 	;
  2550                              <1> 	; 18/10/2015
  2551 00005935 29D2                <1> 	sub	edx, edx
  2552 00005937 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2553                              <1> trans_addr_rw:
  2554 00005939 50                  <1> 	push	eax
  2555 0000593A 53                  <1> 	push	ebx
  2556                              <1> 	; 18/10/2015
  2557 0000593B 52                  <1> 	push 	edx ; r/w sign (in DL)
  2558                              <1> 	;
  2559 0000593C 8B1D[CC740000]      <1> 	mov	ebx, [u.base]
  2560 00005942 E84BD8FFFF          <1> 	call	get_physical_addr ; get physical address
  2561 00005947 730A                <1> 	jnc	short passc_0
  2562 00005949 A3[1C750000]        <1> 	mov	[u.error], eax
  2563                              <1> 	;pop	edx
  2564                              <1> 	;pop 	ebx
  2565                              <1> 	;pop	eax
  2566 0000594E E97BE1FFFF          <1> 	jmp	error
  2567                              <1> passc_0:
  2568 00005953 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2569 00005956 5A                  <1> 	pop	edx ; 18/10/2015
  2570 00005957 7517                <1> 	jnz	short passc_1
  2571                              <1> 	; 18/10/2015
  2572 00005959 20D2                <1> 	and 	dl, dl
  2573 0000595B 7413                <1> 	jz	short passc_1
  2574                              <1> 	; 20/05/2015
  2575                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2576                              <1> 	; EBX = linear address
  2577 0000595D 51                  <1> 	push 	ecx
  2578                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2 (BugFix)
  2579 0000595E 53                  <1> 	push	ebx ;* ; BugFix  ; 31/12/2021
  2580 0000595F E89DD7FFFF          <1> 	call 	copy_page
  2581 00005964 5B                  <1> 	pop	ebx ;* ; BugFix  ; 31/12/2021
  2582 00005965 59                  <1> 	pop	ecx
  2583 00005966 7217                <1> 	jc	short passc_2
  2584                              <1> 	; 30/11/2021
  2585                              <1> 	;push	eax ; physical address of the new/allocated page
  2586                              <1> 	;call	add_to_swap_queue
  2587                              <1> 	;pop	eax
  2588                              <1> 	; 18/10/2015
  2589 00005968 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2590                              <1> 	;mov 	ecx, PAGE_SIZE
  2591                              <1> 	;sub	ecx, ebx 
  2592 0000596E 01D8                <1> 	add	eax, ebx  
  2593                              <1> passc_1: 
  2594                              <1> 	; 18/10/2015
  2595                              <1> 	; 20/05/2015
  2596 00005970 A3[10750000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2597 00005975 66890D[14750000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2598 0000597C 5B                  <1> 	pop	ebx
  2599 0000597D 58                  <1> 	pop	eax
  2600 0000597E C3                  <1> 	retn	; 08/06/2015
  2601                              <1> passc_2:
  2602 0000597F C705[1C750000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2602 00005987 0000                <1>
  2603                              <1> 	;pop 	ebx
  2604                              <1> 	;pop	eax
  2605 00005989 E940E1FFFF          <1> 	jmp	error
  2606                              <1> 
  2607                              <1> 	; 25/12/2021
  2608                              <1> 	; 11/12/2021
  2609                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2610                              <1> writei:
  2611                              <1> 	; 20/05/2015
  2612                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2613                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2614                              <1> 	;
  2615                              <1> 	; Write data to file with inode number in R1
  2616                              <1> 	; 
  2617                              <1> 	; INPUTS ->
  2618                              <1> 	;    r1 - inode number
  2619                              <1> 	;    u.count - byte count to be written
  2620                              <1> 	;    u.base - points to user buffer
  2621                              <1> 	;    u.fofp - points to word with current file offset
  2622                              <1> 	; OUTPUTS ->
  2623                              <1> 	;    u.count - cleared
  2624                              <1> 	;    u.nread - accumulates total bytes passed back	
  2625                              <1> 	; ((AX = R1))
  2626                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2627                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2628                              <1> 
  2629 0000598E 31C9                <1> 	xor	ecx, ecx
  2630 00005990 890D[D4740000]      <1> 	mov 	[u.nread], ecx  ; 0
  2631                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2632                              <1> 		            ; / read or write calls
  2633 00005996 66890D[14750000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2634 0000599D 390D[D0740000]      <1> 	cmp 	[u.count], ecx
  2635                              <1> 	;	; tst u.count / test the byte count specified by the user
  2636 000059A3 7701                <1> 	ja 	short writei_1 ; 1f
  2637                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2638 000059A5 C3                  <1> 	retn
  2639                              <1> 	;	; rts r0 / no, return - no writing to do
  2640                              <1> writei_1: ;1:
  2641                              <1> 	;	; mov r1 ,-(sp) / save the i-node number on the stack
  2642                              <1> 	;cmp 	ax, 40
  2643                              <1> 	;	; cmp r1,$40.
  2644                              <1> 	;	; / does the i-node number indicate a special file?
  2645                              <1>         ;ja	dskw 
  2646                              <1> 	;	; bgt dskw / no, branch to standard file output
  2647                              <1> 
  2648                              <1> 	; 28/11/2021
  2649 000059A6 F605[1A750000]FF    <1> 	test	byte [u.kcall], 0FFh
  2650 000059AD 7505                <1> 	jnz	short writei_2  ; 'writei' called by 'mkdir'
  2651                              <1> 
  2652                              <1> 	; eax = inode number
  2653                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2654 000059AF E850FAFFFF          <1> 	call	iget
  2655                              <1> writei_2:
  2656                              <1> 	; 28/11/2021
  2657                              <1> 	; eax = inode number
  2658                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2659 000059B4 E871020000          <1> 	call	is_regular_file
  2660                              <1> 	;jz	dskw ; regular file 
  2661                              <1> 	; 25/12/2021
  2662 000059B9 7505                <1> 	jnz	short writei_5 ; device file 
  2663                              <1> 	; regular file
  2664 000059BB E9FD000000          <1> 	jmp	dskw
  2665                              <1> writei_5:
  2666                              <1> 	; (20/05/2015)
  2667 000059C0 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2668                              <1> 	
  2669                              <1> 	; 28/11/2021	
  2670                              <1> 	; device file
  2671 000059C1 BB[DB590000]        <1> 	mov	ebx, writei_4
  2672 000059C6 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2673 000059C9 720E                <1> 	jb	short writei_3
  2674 000059CB 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2675 000059CE 7709                <1> 	ja	short writei_3 ; 11/12/2021	
  2676                              <1> 	
  2677                              <1> 	; convert v2 inode number to v1 device inode number
  2678 000059D0 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2679 000059D2 89C1                <1> 	mov	ecx, eax
  2680 000059D4 C0E102              <1> 	shl	cl, 2 ; * 4
  2681 000059D7 01CB                <1> 	add	ebx, ecx
  2682                              <1> writei_3:
  2683 000059D9 FF23                <1> 	jmp	dword [ebx]	
  2684                              <1> 		; jmp *1f-2(r1)
  2685                              <1> 		; / jump table and jump to the appropriate routine
  2686                              <1> writei_4: ;1:
  2687 000059DB [1B580000]          <1> 	dd	null ; 28/11/2021
  2688 000059DF [2B5A0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2689                              <1> 		 ;wtty / tty; r1=2
  2690                              <1> 		 ;wppt / ppt; r1=4
  2691 000059E3 [8D5A0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2692                              <1> 		 ;wmem / mem; r1=6
  2693                              <1> 		 ;wrf0 / rf0
  2694                              <1> 		 ;wrk0 / rk0
  2695                              <1> 		 ;wtap / tap0
  2696                              <1> 		 ;wtap / tap1
  2697                              <1> 		 ;wtap / tap2
  2698                              <1> 		 ;wtap / tap3
  2699                              <1> 		 ;wtap / tap4
  2700                              <1> 		 ;wtap / tap5
  2701                              <1> 		 ;wtap / tap6
  2702                              <1> 		 ;wtap / tap7
  2703 000059E7 [43600000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2704 000059EB [43600000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2705 000059EF [43600000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2706 000059F3 [43600000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2707 000059F7 [43600000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2708 000059FB [43600000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2709 000059FF [7E5A0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2710 00005A03 [785A0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2711                              <1> 		 ;xmtt / tty0
  2712 00005A07 [785A0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2713                              <1> 		 ;xmtt / tty1
  2714 00005A0B [785A0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2715                              <1> 		 ;xmtt / tty2
  2716 00005A0F [785A0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2717                              <1> 		 ;xmtt / tty3
  2718 00005A13 [785A0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2719                              <1> 		 ;xmtt / tty4
  2720 00005A17 [785A0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2721                              <1> 		 ;xmtt / tty5
  2722 00005A1B [785A0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2723                              <1> 		 ;xmtt / tty6
  2724 00005A1F [785A0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2725                              <1> 		 ;xmtt / tty7
  2726 00005A23 [785A0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2727                              <1> 		; / wlpr / lpr
  2728 00005A27 [785A0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)
  2729                              <1> 
  2730                              <1> ;	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2731                              <1> ;null:
  2732                              <1> ;	xor	eax, eax
  2733                              <1> ;	pop	eax
  2734                              <1> ;	retn	
  2735                              <1> 
  2736                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2737                              <1> wtty: ; write to console tty (write to screen)
  2738                              <1> 	; 18/11/2015
  2739                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2740                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2741                              <1> 	;
  2742                              <1> 	; Console tty output is on current video page
  2743                              <1> 	; Console tty character output procedure is changed here
  2744                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2745                              <1> 	;
  2746 00005A2B 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2747 00005A32 8AA3[C3700000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2748 00005A38 88E0                <1> 	mov	al, ah ; 07/07/2014
  2749                              <1> wttys:	
  2750                              <1> 	; 10/10/2013
  2751 00005A3A 8825[DD740000]      <1> 	mov 	[u.ttyn], ah
  2752                              <1> 	; 13/01/2014
  2753 00005A40 FEC0                <1> 	inc	al
  2754 00005A42 A2[DF740000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2755                              <1> wtty_nc: ; 15/05/2013
  2756                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2757 00005A47 E8FD000000          <1> 	call	cpass
  2758                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2759                              <1> 		             ; / none go to return address in syswrite
  2760                              <1> 		; tst r1 / is character = null
  2761                              <1> 		; beq wtty / yes, get next character
  2762                              <1> 	; 10/10/2013
  2763 00005A4C 7428                <1> 	jz	short wret
  2764                              <1> 	;1 :
  2765                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2766                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2767                              <1> 		;	          / than 20
  2768                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2769                              <1> 	; 27/06/2014
  2770                              <1> wtty_1:
  2771                              <1> 	; AH = tty number
  2772                              <1> 	; AL = ASCII code of the character
  2773                              <1> 	; 15/04/2014
  2774                              <1> 	;push	ax
  2775                              <1> 	; 11/12/2021
  2776 00005A4E 50                  <1> 	push	eax
  2777 00005A4F E82B0A0000          <1> 	call	putc ; 14/05/2013
  2778 00005A54 731D                <1> 	jnc	short wtty_2
  2779                              <1> 	; 18/11/2015
  2780 00005A56 E814F5FFFF          <1> 	call	idle
  2781                              <1> 	;mov	ax, [esp]
  2782                              <1> 	; 11/12/2021
  2783 00005A5B 8B0424              <1> 	mov	eax, [esp]
  2784 00005A5E E81C0A0000          <1> 	call	putc
  2785 00005A63 730E                <1> 	jnc	short wtty_2 
  2786                              <1> 	; 02/06/2014
  2787 00005A65 8A25[DD740000]      <1> 	mov	ah, [u.ttyn]
  2788 00005A6B E892F5FFFF          <1> 	call	sleep
  2789                              <1> 	;pop	ax
  2790                              <1> 	; 11/12/2021
  2791 00005A70 58                  <1> 	pop	eax
  2792 00005A71 EBDB                <1> 	jmp 	short wtty_1
  2793                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2794                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2795                              <1> 			      ; / console tty and
  2796                              <1> 		; br 	2f / place character in list; if none available
  2797                              <1> 		   	  ; / branch to put process to sleep
  2798                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2799                              <1> wtty_2:
  2800                              <1> 	; 15/04/2014
  2801                              <1> 	;pop	ax
  2802                              <1> 	; 11/12/2021
  2803 00005A73 58                  <1> 	pop	eax
  2804 00005A74 EBD1                <1> 	jmp	short wtty_nc
  2805                              <1> 		; br wtty
  2806                              <1> wret:	; 10/10/2013 (20/05/2015)
  2807 00005A76 58                  <1> 	pop	eax
  2808 00005A77 C3                  <1> 	retn
  2809                              <1> 	;2:
  2810                              <1> 		;mov	r1,-(sp) / place character on stack
  2811                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2812                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2813                              <1> 		;br	1b / try again to place character in clist and output
  2814                              <1> 
  2815                              <1> xmtt:   ; < send/write character to tty >
  2816                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2817                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2818                              <1> 	;
  2819                              <1> 	; Retro UNIX 8086 v1 modification !
  2820                              <1> 	; 
  2821                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2822                              <1> 	;		(exactly different than this one)
  2823                              <1> 	;	was in 'u9.s' file.
  2824                              <1> 	;
  2825 00005A78 2C0A                <1> 	sub 	al, 10
  2826                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2827                              <1> 	; 10/10/2013
  2828 00005A7A 88C4                <1> 	mov	ah, al
  2829                              <1> 	; 28/07/2013
  2830 00005A7C EBBC                <1> 	jmp	short wttys
  2831                              <1> 
  2832                              <1> ;wppt:
  2833                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2834                              <1> ;		         / if none return to writei's calling routine
  2835                              <1> ;	jsr	r0,pptoc / output character on ppt
  2836                              <1> ;	br	wppt
  2837                              <1> wlpr:
  2838 00005A7E C705[1C750000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2838 00005A86 0000                <1>
  2839 00005A88 E941E0FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2840                              <1> 		;/	jsr	r0,cpass
  2841                              <1> 		;/	cmp	r0,$'a
  2842                              <1> 		;/	blo	1f
  2843                              <1> 		;/	cmp	r1,$'z
  2844                              <1> 		;/	bhi	1f
  2845                              <1> 		;/	sub	$40,r1
  2846                              <1> 		;/1:
  2847                              <1> 		;/	jsr	r0,lptoc
  2848                              <1> 		;/	br	wlpr
  2849                              <1> 		; br rmem / continue
  2850                              <1> 
  2851                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2852                              <1> 	; 17/10/2015
  2853                              <1> 	; 11/06/2015
  2854                              <1> 	; 24/05/2015
  2855                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2856                              <1> 	;
  2857 00005A8D 813D[0F070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2857 00005A93 [924F0000]          <1>
  2858 00005A97 7415                <1>         je      short wmem_acc_err
  2859                              <1> 	;
  2860 00005A99 8B35[BC740000]      <1>         mov     esi, [u.fofp] 
  2861                              <1> wmem_1:
  2862 00005A9F E8A5000000          <1> 	call	cpass
  2863                              <1> 		; jsr r0,cpass / get next character from users area of
  2864                              <1> 			     ; / core and put it in r1
  2865                              <1>         	; mov r1,-(sp) / put character on the stack
  2866                              <1> 	; 20/09/2013
  2867 00005AA4 74D0                <1> 	jz	short wret ; wmem_2  
  2868 00005AA6 8B1E                <1>         mov     ebx, [esi]
  2869                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2870 00005AA8 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2871                              <1> 		; inc *u.fofp / increment file offset to point to next
  2872                              <1> 			    ; / available location in file
  2873 00005AAA 8803                <1> 	mov	[ebx], al	
  2874                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2875                              <1> 			        ; / assigned to it
  2876 00005AAC EBF1                <1> 	jmp	short wmem_1
  2877                              <1> 		; br wmem / continue
  2878                              <1> 	;1:
  2879                              <1> 	;jmp	error / ?
  2880                              <1> ;wmem_2:	
  2881                              <1> ;	; 20/09/2013
  2882                              <1> ;	pop	ax
  2883                              <1> ;	retn
  2884                              <1> 
  2885                              <1> wmem_acc_err:
  2886 00005AAE C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2886 00005AB6 0000                <1>
  2887 00005AB8 E911E0FFFF          <1> 	jmp	error
  2888                              <1> 
  2889                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2890                              <1> 
  2891                              <1> dskw: ; / write routine for non-special files
  2892                              <1> 	;
  2893                              <1> 	; 28/11/2021
  2894                              <1> 	; 25/07/2015
  2895                              <1> 	; 16/06/2015
  2896                              <1> 	; 09/06/2015
  2897                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2898                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2899                              <1> 
  2900                              <1> 	; 01/08/2013 (mkdir_w check)
  2901                              <1> 	;push	ax ; 26/04/2013
  2902                              <1> 	;	; mov (sp),r1 / get an i-node number from the stack into r1
  2903                              <1> 	; 28/11/2021
  2904 00005ABD 50                  <1> 	push	eax
  2905                              <1> 	; AX = inode number
  2906 00005ABE E841F9FFFF          <1> 	call	iget
  2907                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2908                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2909 00005AC3 8B1D[BC740000]      <1>         mov     ebx, [u.fofp] 
  2910 00005AC9 8B13                <1> 	mov 	edx, [ebx]
  2911                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2912                              <1> 			       ; / in the fsp entry for this file] in r2
  2913 00005ACB 0315[D0740000]      <1> 	add 	edx, [u.count]	
  2914                              <1> 		; add u.count,r2 / no. of bytes to be written
  2915                              <1> 			       ; / + file offset is put in r2
  2916                              <1> 	;; 16/06/2015        
  2917                              <1> 	;cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2918                              <1> 	;jna	short dskw_0
  2919                              <1> 	;mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2920                              <1> 	;jmp	error
  2921                              <1> dskw_0:	
  2922                              <1> 	; 28/11/2021
  2923 00005AD1 3B15[4C700000]      <1> 	cmp	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2924                              <1> 	;cmp	dx, [i.size]
  2925                              <1> 	;	; cmp r2,i.size / is this greater than the present size of
  2926                              <1> 		              ; / the file?
  2927 00005AD7 760B                <1> 	jna	short dskw_1
  2928                              <1> 		; blos 1f / no, branch
  2929 00005AD9 8915[4C700000]      <1> 	mov	[i.size], edx ; 32 bit file size (runix v2 inode)
  2930                              <1> 	;mov	[i.size], dx
  2931                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2932                              <1> 			      ; / file offset + no. of data bytes
  2933 00005ADF E8BFFAFFFF          <1> 	call	setimod
  2934                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2935                              <1> 		          ; / modified), stuff time of modification into
  2936                              <1> 	          	  ; / core image of i-node
  2937                              <1> dskw_1: ; 1:
  2938                              <1> 	; 28/11/2021
  2939                              <1> 	;call	mget
  2940 00005AE4 E899F5FFFF          <1> 	call	mget_w
  2941                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2942                              <1> 			    ; /	the next data byte
  2943                              <1> 	; eax = physical block/sector number
  2944 00005AE9 8B1D[BC740000]      <1> 	mov     ebx, [u.fofp]
  2945 00005AEF 8B13                <1> 	mov	edx, [ebx]
  2946 00005AF1 81E2FF010000        <1> 	and	edx, 1FFh  
  2947                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2948 00005AF7 750C                <1> 	jnz	short dskw_2
  2949                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2950                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2951 00005AF9 813D[D0740000]0002- <1> 	cmp	dword [u.count], 512
  2951 00005B01 0000                <1>
  2952                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2953                              <1> 				  ; / an entire block? (i.e., no. of
  2954 00005B03 7305                <1> 	jnb	short dskw_3
  2955                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2956                              <1> 			; / Yes, branch. Don't have to read block
  2957                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2958                              <1>    		; / overwritten).
  2959 00005B05 E8FF050000          <1> 	call	dskrd
  2960                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2961                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2962                              <1> dskw_3: ; 3:
  2963                              <1> 	; EAX (r1) = block/sector number
  2964 00005B0A E86C060000          <1> 	call	wslot
  2965                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2966                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2967 00005B0F 803D[1A750000]00    <1> 	cmp	byte [u.kcall], 0
  2968 00005B16 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2969                              <1> 	;
  2970 00005B18 66833D[14750000]00  <1> 	cmp	word [u.pcount], 0
  2971 00005B20 7705                <1> 	ja	short dskw_5
  2972                              <1> dskw_4:
  2973                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2974 00005B22 E80AFEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2975                              <1> dskw_5:
  2976                              <1> 	; eBX (r5) = system (I/O) buffer address
  2977 00005B27 E87D000000          <1> 	call	sioreg
  2978                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2979                              <1> 			     ; / r1 = address of data, r2 points to location
  2980                              <1> 			     ; / in buffer in which to start writing data
  2981                              <1> 	; eSI = file (user data) offset
  2982                              <1> 	; eDI = sector (I/O) buffer offset
  2983                              <1> 	; eCX = byte count
  2984                              <1> 	;
  2985 00005B2C F3A4                <1>   	rep	movsb
  2986                              <1> 		; movb (r1 )+,(r2)+ 
  2987                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2988                              <1> 		; dec r3 / decrement no. of bytes to be written
  2989                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2990                              <1> 	; 25/07/2015
  2991                              <1> 	; eax = remain bytes in buffer
  2992                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2993 00005B2E 09C0                <1> 	or	eax, eax
  2994 00005B30 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2995                              <1> dskw_6:
  2996 00005B32 E860060000          <1> 	call	dskwr
  2997                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2998 00005B37 833D[D0740000]00    <1>         cmp     dword [u.count], 0
  2999                              <1> 		; tst u.count / any more data to write?
  3000 00005B3E 77A4                <1> 	ja	short dskw_1
  3001                              <1> 		; bne 1b / yes, branch
  3002                              <1> 	; 03/08/2013
  3003 00005B40 C605[1A750000]00    <1> 	mov	byte [u.kcall], 0
  3004                              <1> 	; 20/09/2013 (;;)
  3005                              <1> 	;pop	ax
  3006                              <1> 	; 28/11/2021
  3007 00005B47 58                  <1> 	pop	eax  
  3008 00005B48 C3                  <1> 	retn
  3009                              <1> 	;;jmp 	short dskw_ret 
  3010                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3011                              <1> 
  3012                              <1> 	; 24/12/2021
  3013                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3014                              <1> cpass: ; / get next character from user area of core and put it in r1
  3015                              <1> 	; 18/10/2015
  3016                              <1> 	; 10/10/2015
  3017                              <1> 	; 10/07/2015
  3018                              <1> 	; 02/07/2015
  3019                              <1> 	; 01/07/2015
  3020                              <1> 	; 24/06/2015
  3021                              <1> 	; 08/06/2015
  3022                              <1> 	; 04/06/2015
  3023                              <1> 	; 20/05/2015
  3024                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3025                              <1> 	;
  3026                              <1> 	; INPUTS -> 
  3027                              <1> 	;     [u.base] = virtual address in user area
  3028                              <1> 	;     [u.count] = byte count (max.)
  3029                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3030                              <1> 	; OUTPUTS -> 
  3031                              <1> 	;     AL = the character which is pointed by [u.base]
  3032                              <1> 	;     zf = 1 -> transfer count has been completed	
  3033                              <1>         ;
  3034                              <1> 	; ((Modified registers: EAX, EDX, ECX))
  3035                              <1> 	;
  3036                              <1> 	;
  3037 00005B49 833D[D0740000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3038                              <1> 		; tst u.count / have all the characters been transferred
  3039                              <1> 			    ; / (i.e., u.count, # of chars. left
  3040 00005B50 763F                <1> 	jna	short cpass_3
  3041                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3042 00005B52 FF0D[D0740000]      <1> 	dec	dword [u.count]
  3043                              <1> 		; dec u.count / no, decrement u.count
  3044                              <1>         ; 19/05/2015 
  3045                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3046                              <1> 	;		      to physical address
  3047 00005B58 66833D[14750000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3048                              <1> 			     ; 1-4095 --> use previous physical base address
  3049                              <1> 			     ; in [u.pbase]
  3050 00005B60 770E                <1> 	ja	short cpass_1
  3051                              <1> 	; 02/07/2015
  3052 00005B62 833D[0C750000]00    <1> 	cmp	dword [u.ppgdir], 0  ; is the caller os kernel
  3053 00005B69 7427                <1> 	je	short cpass_k 	; (sysexec, '/etc/init') ? 
  3054                              <1> 	; 08/06/2015 - 10/07/2015
  3055 00005B6B E8C1FDFFFF          <1> 	call	trans_addr_r
  3056                              <1> cpass_1:
  3057                              <1> 	; 02/07/2015
  3058                              <1> 	; 24/06/2015
  3059 00005B70 66FF0D[14750000]    <1> 	dec	word [u.pcount]
  3060                              <1> cpass_2: 
  3061                              <1> 	; 10/10/2015
  3062                              <1> 	; 02/07/2015
  3063 00005B77 8B15[10750000]      <1> 	mov	edx, [u.pbase]
  3064 00005B7D 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3065                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3066                              <1> 				; / by u.base and put it in r1
  3067 00005B7F FF05[D4740000]      <1> 	inc	dword [u.nread]
  3068                              <1> 		; inc u.nread / increment no. of bytes transferred
  3069 00005B85 FF05[CC740000]      <1> 	inc	dword [u.base]
  3070                              <1> 		; inc u.base / increment the buffer address to point to the
  3071                              <1> 			   ; / next byte
  3072 00005B8B FF05[10750000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3073                              <1> cpass_3:
  3074 00005B91 C3                  <1> 	retn
  3075                              <1> 		; rts	r0 / next byte
  3076                              <1> 	; 1: 
  3077                              <1> 		; mov (sp)+,r0 
  3078                              <1> 		         ; / put return address of calling routine into r0
  3079                              <1> 		; mov (sp)+,r1 / i-number in r1
  3080                              <1> 		; rts r0 / non-local return
  3081                              <1> cpass_k:
  3082                              <1> 	; 02/07/2015
  3083                              <1> 	; The caller is os kernel 
  3084                              <1> 	; (get sysexec arguments from kernel's memory space)
  3085                              <1> 	;
  3086 00005B92 8B1D[CC740000]      <1> 	mov	ebx, [u.base]
  3087 00005B98 66C705[14750000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3087 00005BA0 10                  <1>
  3088 00005BA1 891D[10750000]      <1> 	mov	[u.pbase], ebx
  3089 00005BA7 EBCE                <1> 	jmp	short cpass_2
  3090                              <1> 	
  3091                              <1> sioreg: 
  3092                              <1> 	; 25/07/2015
  3093                              <1> 	; 18/07/2015
  3094                              <1> 	; 02/07/2015
  3095                              <1> 	; 17/06/2015
  3096                              <1> 	; 09/06/2015
  3097                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3098                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3099                              <1> 	;
  3100                              <1> 	; INPUTS -> 
  3101                              <1> 	;     eBX = system buffer (data) address (r5)
  3102                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3103                              <1> 	;     [u.base] = virtual address of the user buffer
  3104                              <1> 	;     [u.pbase] = physical address of the user buffer
  3105                              <1> 	;     [u.count] = byte count
  3106                              <1> 	;     [u.pcount] = byte count within page frame 			
  3107                              <1> 	; OUTPUTS -> 
  3108                              <1> 	;     eSI = user data offset (r1)
  3109                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3110                              <1> 	;     eCX = byte count (r3)
  3111                              <1> 	;     EAX = remain bytes after byte count within page frame
  3112                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3113                              <1>         ;
  3114                              <1> 	; ((Modified registers:  EDX))
  3115                              <1>  
  3116 00005BA9 8B35[BC740000]      <1>         mov     esi, [u.fofp]
  3117 00005BAF 8B3E                <1>         mov     edi, [esi]
  3118                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3119 00005BB1 89F9                <1> 	mov	ecx, edi
  3120                              <1> 		; mov r2,r3 / and also to r3
  3121 00005BB3 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3122                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3123 00005BB9 81E7FF010000        <1> 	and	edi, 1FFh
  3124                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3125 00005BBF 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3126                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3127                              <1> 			  ; / where data is to be placed
  3128                              <1>                 ; mov u.base,r1 / address of data is in r1
  3129 00005BC1 F7D9                <1> 	neg	ecx
  3130                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3131                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3132 00005BC3 3B0D[D0740000]      <1> 	cmp	ecx, [u.count]
  3133                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3134                              <1> 			       ; / to be written to the file
  3135 00005BC9 7606                <1> 	jna	short sioreg_0
  3136                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3137                              <1> 			 ; / in the file block as the number to be written
  3138 00005BCB 8B0D[D0740000]      <1> 	mov	ecx, [u.count]
  3139                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3140                              <1> 			       ; / bytes as the number to be written
  3141                              <1> sioreg_0:
  3142                              <1> 	; 17/06/2015
  3143 00005BD1 803D[1A750000]00    <1> 	cmp	byte [u.kcall], 0 
  3144 00005BD8 7613                <1> 	jna	short sioreg_1
  3145                              <1> 	; 25/07/2015
  3146                              <1> 	 ; the caller is 'mkdir' or 'namei'
  3147 00005BDA A1[CC740000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3148 00005BDF A3[10750000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3149 00005BE4 66890D[14750000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3150 00005BEB EB0B                <1> 	jmp	short sioreg_2
  3151                              <1> sioreg_1:
  3152                              <1> 	; 25/07/2015
  3153                              <1> 	; 18/07/2015
  3154                              <1> 	; 09/06/2015 
  3155 00005BED 0FB715[14750000]    <1> 	movzx	edx, word [u.pcount]
  3156                              <1> 		; ecx and [u.pcount] are always > 0, here
  3157 00005BF4 39D1                <1> 	cmp	ecx, edx	
  3158 00005BF6 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3159                              <1> sioreg_2: ; 2:
  3160 00005BF8 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3161                              <1> sioreg_3:
  3162 00005BFA 010D[D4740000]      <1> 	add 	[u.nread], ecx
  3163                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3164                              <1> 			         ; / during write is put into u.nread
  3165 00005C00 290D[D0740000]      <1> 	sub 	[u.count], ecx
  3166                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3167                              <1> 			       ; / must be written or read
  3168 00005C06 010D[CC740000]      <1> 	add 	[u.base], ecx
  3169                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3170                              <1> 			      ; / data bytes
  3171 00005C0C 010E                <1>         add 	[esi], ecx 
  3172                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3173                              <1> 			       ; / + old file offset
  3174                              <1> 	; 25/07/2015
  3175 00005C0E 8B35[10750000]      <1> 	mov	esi, [u.pbase]
  3176 00005C14 66290D[14750000]    <1> 	sub	[u.pcount], cx
  3177 00005C1B 010D[10750000]      <1> 	add	[u.pbase], ecx
  3178 00005C21 C3                  <1>         retn
  3179                              <1> 		; rts r0
  3180                              <1> 		; transfer count > [u.pcount]
  3181                              <1> sioreg_4:
  3182                              <1> 	; 25/07/2015
  3183                              <1> 	; transfer count > [u.pcount] 
  3184                              <1> 	; (ecx > edx)
  3185 00005C22 89C8                <1> 	mov	eax, ecx
  3186 00005C24 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3187 00005C26 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3188 00005C28 EBD0                <1> 	jmp	short sioreg_3
  3189                              <1> 
  3190                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  3191                              <1> is_regular_file:
  3192                              <1> 	; check if it is a regular file or device file inode
  3193                              <1> 	;
  3194                              <1> 	; INPUT:
  3195                              <1> 	;	current inode
  3196                              <1> 	; OUTPUT:
  3197                              <1> 	;	cf = 0 and zf = 1 -> regular file
  3198                              <1> 	;	cf = 0 and zf = 0 -> device file
  3199                              <1> 	;	cf = 1 -> invalid file (jump to 'error')
  3200                              <1> 	;
  3201                              <1> 	; Modified registers: ecx (cl)
  3202                              <1> 
  3203                              <1> 	; 28/11/2021
  3204 00005C2A 8A0D[45700000]      <1> 	mov	cl, [i.flgs+1]
  3205 00005C30 F6C180              <1> 	test	cl, 80h		; regular file ?
  3206 00005C33 7514                <1> 	jnz	short isregf_1  ; yes 
  3207 00005C35 80E120              <1> 	and	cl, 20h 	; device file ?
  3208 00005C38 7511                <1> 	jnz	short isregf_2  ; yes 
  3209                              <1> 
  3210                              <1> 	; 28/11/2021
  3211                              <1> 	; invalid inode/file type !
  3212 00005C3A C705[1C750000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  3212 00005C42 0000                <1>
  3213                              <1> 	;stc
  3214                              <1> 	;retn
  3215 00005C44 E985DEFFFF          <1> 	jmp	error
  3216                              <1> isregf_1:
  3217 00005C49 30C9                <1> 	xor	cl, cl  ; cl = 0
  3218                              <1> 	; zf = 1
  3219                              <1> 	;retn
  3220                              <1> isregf_2:
  3221                              <1> 	; zf = 0
  3222                              <1> 	; cl = 20h
  3223 00005C4B C3                  <1> 	retn	
  2078                                  %include 'u7.s'      ; 18/04/2015
  2079                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2080                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2081                              <1> ; ****************************************************************************
  2082                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC
  2083                              <1> ; Last Modification: 11/02/2022
  2084                              <1> ; ----------------------------------------------------------------------------
  2085                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2086                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2087                              <1> ;
  2088                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2089                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2090                              <1> ; <Bell Laboratories (17/3/1972)>
  2091                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2092                              <1> ;
  2093                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2094                              <1> ;
  2095                              <1> ; ****************************************************************************
  2096                              <1> 
  2097                              <1> sysmount: ; / mount file system; args special; name
  2098                              <1> 	; 08/02/2022
  2099                              <1> 	; 07/02/2022
  2100                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2101                              <1> 	; 14/11/2015
  2102                              <1> 	; 24/10/2015
  2103                              <1> 	; 13/10/2015
  2104                              <1> 	; 10/07/2015
  2105                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2106                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2107                              <1> 	;
  2108                              <1> 	; 'sysmount' anounces to the system that a removable 
  2109                              <1> 	; file system has been mounted on a special file.
  2110                              <1> 	; The device number of the special file is obtained via
  2111                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2112                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2113                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2114                              <1> 	; to read file system into core, i.e. the first block on the
  2115                              <1> 	; mountable file system is read in. This block is super block
  2116                              <1> 	; for the file system. This call is super user restricted.	
  2117                              <1> 	;
  2118                              <1> 	; Calling sequence:
  2119                              <1> 	;	sysmount; special; name
  2120                              <1> 	; Arguments:
  2121                              <1> 	;	special - pointer to name of special file (device)
  2122                              <1> 	;	name -  pointer to name of the root directory of the
  2123                              <1> 	;		newly mounted file system. 'name' should 
  2124                              <1> 	;		always be a directory.
  2125                              <1> 	; Inputs: - 
  2126                              <1> 	; Outputs: -
  2127                              <1> 	; ...............................................................
  2128                              <1> 	;				
  2129                              <1> 	; Retro UNIX 8086 v1 modification: 
  2130                              <1> 	;       'sysmount' system call has two arguments; so,
  2131                              <1> 	;	* 1st argument, special is pointed to by BX register
  2132                              <1> 	;	* 2nd argument, name is in CX register
  2133                              <1> 	;
  2134                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2135                              <1> 	;	       already modified for IBM PC compatibility and 
  2136                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2137                              <1> 	
  2138                              <1> 	;call	arg2
  2139                              <1> 		; jsr r0,arg2 / get arguments special and name
  2140 00005C4C 891D[C4740000]      <1> 	mov	[u.namep], ebx
  2141                              <1> 	; 07/02/2022
  2142                              <1> 	;push	ecx ; directory name
  2143                              <1> 	;cmp	dword [mnti], 0 ; 11/01/2022 (32 bit inode number)
  2144 00005C52 66833D[94740000]00  <1> 	cmp	word [mnti], 0
  2145                              <1> 		; tst mnti / is the i-number of the cross device file
  2146                              <1> 			 ; / zero?
  2147                              <1> 	;;ja	error
  2148                              <1>         	; bne errora / no, error
  2149                              <1> 	;ja	sysmnt_err0
  2150                              <1> 	; 11/01/2022
  2151 00005C5A 7605                <1> 	jna	short sysmnt_0 ; 12/01/2022
  2152 00005C5C E901010000          <1> 	jmp	sysmnt_err0
  2153                              <1> sysmnt_0:
  2154                              <1> 	; 07/02/2022
  2155 00005C61 51                  <1> 	push	ecx ; directory name
  2156 00005C62 E8E3000000          <1> 	call	getspl
  2157                              <1> 		; jsr r0,getspl / get special files device number in r1
  2158                              <1> 	; 07/02/2022
  2159 00005C67 8F05[C4740000]      <1> 	pop	dword [u.namep] ; directory name
  2160                              <1> 	; 13/10/2015
  2161                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2162                              <1>         ; 11/01/2022
  2163 00005C6D 29DB                <1> 	sub	ebx, ebx
  2164 00005C6F 88C3                <1> 	mov	bl, al
  2165 00005C71 F683[CA6A0000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2166 00005C78 750F                <1> 	jnz	short sysmnt_1
  2167                              <1> sysmnt_err1:
  2168 00005C7A C705[1C750000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2168 00005C82 0000                <1>
  2169 00005C84 E945DEFFFF          <1> 	jmp	error
  2170                              <1> sysmnt_1:
  2171                              <1> 	; 07/02/2022
  2172                              <1> 	;pop	dword [u.namep]
  2173                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2174                              <1> 				  ; / on the device
  2175                              <1> 	; 14/11/2015
  2176 00005C89 53                  <1> 	push	ebx ; 13/10/2015
  2177                              <1> 		; mov r1,-(sp) / save the device number
  2178                              <1>         ;
  2179 00005C8A E8E0ECFFFF          <1> 	call	namei
  2180                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2181                              <1> 		       ; ax = 0 -> file not found 	
  2182                              <1> 	;jz	error
  2183                              <1> 	;jc	error
  2184                              <1> 		; jsr r0,namei / get the i-number of the file
  2185                              <1>                	; br errora
  2186 00005C8F 730F                <1> 	jnc	short sysmnt_2
  2187                              <1> sysmnt_err2:
  2188 00005C91 C705[1C750000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2188 00005C99 0000                <1>
  2189 00005C9B E92EDEFFFF          <1> 	jmp	error
  2190                              <1> sysmnt_2:
  2191                              <1> 	; 11/01/2022
  2192 00005CA0 A3[94740000]        <1> 	mov	[mnti], eax ; 32 bit inode number (<= 65535)	
  2193                              <1> 	;mov	[mnti], ax
  2194                              <1>         	; mov r1,mnti / put it in mnti
  2195                              <1> 	; 11/01/2022
  2196 00005CA5 BB[54770000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2197                              <1> sysmnt_3: ;1:
  2198                              <1>         ;cmp	byte [ebx+1], 0
  2199                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2200                              <1> 			   ; / dismountable device set?
  2201                              <1>         ;jna	short sysmnt_4		
  2202                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2203                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2204                              <1> 	;jmp	short sysmnt_3
  2205                              <1> sysmnt_4:   
  2206 00005CAA 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2207 00005CAB A2[8B740000]        <1> 	mov	[mdev], al
  2208                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2209 00005CB0 8803                <1> 	mov	[ebx], al
  2210                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2211                              <1> 			      ; / of the I/O queue entry
  2212                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2213                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2214 00005CB2 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2215                              <1> 		; bis $2000,sb1 / set the read bit
  2216                              <1> 	; Retro UNIX 386 v1 modification : 
  2217                              <1> 	;	32 bit block number at buffer header offset 4
  2218 00005CB7 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2219 00005CBE E827060000          <1> 	call 	diskio
  2220 00005CC3 7345                <1> 	jnc	short sysmnt_5
  2221 00005CC5 31C0                <1> 	xor 	eax, eax
  2222 00005CC7 66A3[94740000]      <1> 	mov	[mnti], ax ; 0
  2223 00005CCD A2[8B740000]        <1> 	mov	[mdev], al ; 0
  2224                              <1> 	;mov	[cdev], al ; 0
  2225                              <1> 	; 08/02/2022
  2226 00005CD2 803D[1B750000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2227 00005CD9 7508                <1> 	jne	short sysmnt_err3
  2228                              <1> 	; yes, clear [u.brwdev] for next check
  2229                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2230 00005CDB FE05[1B750000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2231 00005CE1 EB0A                <1> 	jmp	short sysmnt_err4
  2232                              <1> sysmnt_err3:	; 08/02/2022
  2233                              <1> 	; no, set [u.error] to disk read error
  2234 00005CE3 C705[1C750000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2234 00005CEB 0000                <1>
  2235                              <1> sysmnt_err4:
  2236                              <1> 	; 08/02/2022
  2237                              <1> 	; 14/11/2015
  2238 00005CED FEC8                <1> 	dec 	al
  2239 00005CEF 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2240 00005CF1 FEC0                <1> 	inc	al
  2241 00005CF3 48                  <1> 	dec	eax
  2242 00005CF4 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2243 00005CF7 E9D2DDFFFF          <1> 	jmp	error
  2244                              <1> sysmnt_invd:
  2245                              <1> 	; 08/02/2022
  2246 00005CFC C705[1C750000]1C00- <1> 	mov	dword [u.error], ERR_INV_FS ; 28
  2246 00005D04 0000                <1>
  2247                              <1> 				 ;'invalid fs/superblock !' error
  2248 00005D06 30C0                <1> 	xor	al, al ; 0
  2249 00005D08 EBE3                <1> 	jmp	short sysmnt_err4
  2250                              <1> 
  2251                              <1> sysmnt_5:
  2252                              <1> 	; 08/02/2022
  2253                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1 BugFix)
  2254                              <1> 	;  v1.2 Note: This code will be changed for hard disk partitions
  2255                              <1> 	;	    ! (for now, rufs v2 floppy disks can be mounted) !		
  2256                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2257                              <1> 	; (Following check is needed to prevent mounting an
  2258                              <1> 	; invalid file system (invalid super block).
  2259                              <1> 	; 
  2260 00005D0A 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2261 00005D0D C0E002              <1> 	shl	al, 2 ; 4*index
  2262 00005D10 8B88[AE6A0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2263                              <1> 	;shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2264                              <1> 	; ecx = number of free map bytes (required)
  2265                              <1> 	;;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2266                              <1> 	;movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2267                              <1> 	; edx = number of free blocks map bytes
  2268                              <1> 	;;shl	edx, 3 ; convert free map bytes to free map bits
  2269                              <1> 	;cmp	ecx, edx ; compare free map bits and volume size
  2270                              <1> 	;		 ; (in sectors), if they are not equal
  2271                              <1> 	;		 ; the disk to be mounted is an...
  2272                              <1> 	;jne	short sysmnt_invd ; invalid disk !
  2273                              <1> 	;		 ; (which has not got a valid super bloc	
  2274                              <1> 	; 07/02/2022
  2275                              <1> 	;xor	al, al ; 08/02/2022
  2276                              <1> 	; 11/01/2022
  2277                              <1> 	; Retro UNIX 386 v2 superblock (offset 8, volume size)
  2278 00005D16 8B5310              <1> 	mov	edx, [ebx+16] ; SB.VolumeSize (in sectors)
  2279 00005D19 39D1                <1> 	cmp	ecx, edx ; compare SB.VolumeSize and Disk volume size
  2280                              <1> 			 ; (in sectors), if they are not equal
  2281                              <1> 			 ; the disk to be mounted is an...	
  2282 00005D1B 75DF                <1> 	jne	short sysmnt_invd ; invalid disk !
  2283                              <1> 			 ; (which has not got a valid shuper block)
  2284                              <1> 	;
  2285 00005D1D C6430100            <1> 	mov	byte [ebx+1], 0
  2286                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2287                              <1> ;sysmnt_6: ;1:
  2288                              <1> 	;;cmp	byte [sb1+1], 0
  2289                              <1> 		; tstb sb1+1 / done reading?
  2290                              <1>    	;;jna	sysret
  2291                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2292                              <1> 	;;jmp	short sysmnt_6
  2293                              <1> 		;bne 1b / no, wait
  2294                              <1>         	;br sysreta / yes
  2295 00005D21 E9C8DDFFFF          <1> 	jmp	sysret
  2296                              <1> 
  2297                              <1> sysumount: ; / special dismount file system
  2298                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2299                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2300                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2301                              <1> 	;
  2302                              <1> 	; 04/11/2013
  2303                              <1> 	; 09/07/2013
  2304                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2305                              <1> 	; indicated as an argument is no longer contain a removable
  2306                              <1> 	; file system. 'getspl' gets the device number of the special
  2307                              <1> 	; file. If no file system was mounted on that device an error
  2308                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2309                              <1> 	; to 'sysret'.
  2310                              <1> 	;
  2311                              <1> 	; Calling sequence:
  2312                              <1> 	;	sysmount; special
  2313                              <1> 	; Arguments:
  2314                              <1> 	;	special - special file to dismount (device)
  2315                              <1> 	;
  2316                              <1> 	; Inputs: - 
  2317                              <1> 	; Outputs: -
  2318                              <1> 	; ...............................................................
  2319                              <1> 	;				
  2320                              <1> 	; Retro UNIX 8086 v1 modification: 
  2321                              <1> 	;       'sysumount' system call has one argument; so,
  2322                              <1> 	;	* Single argument, special is pointed to by BX register
  2323                              <1> 	;
  2324                              <1> 	
  2325                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2326                              <1> 	;call	arg
  2327                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2328 00005D26 891D[C4740000]      <1>         mov	[u.namep], ebx
  2329 00005D2C E819000000          <1> 	call	getspl
  2330                              <1> 		; jsr r0,getspl / get the device number in r1
  2331 00005D31 3A05[8B740000]      <1> 	cmp	al, [mdev]
  2332                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2333 00005D37 7529                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2334                              <1> 	;jne	error
  2335                              <1>         	; bne errora / no error
  2336 00005D39 30C0                <1> 	xor	al, al ; ah = 0
  2337                              <1> 	; (eax = 0) ; 11/01/2022
  2338                              <1> sysumnt_0: ;1:
  2339                              <1>      	; 11/01/2022
  2340                              <1> 	;cmp 	[sb1+1], al ; 0
  2341                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2342                              <1> 	;		   ; / (inhibit bit set)?
  2343                              <1> 	;jna	short sysumnt_1		
  2344                              <1> 	;	; bne 1b / yes, wait
  2345                              <1> 	;call	idle ; (wait for hardware interrupt)
  2346                              <1> 	;jmp	short sysumnt_0
  2347                              <1> sysumnt_1:        
  2348 00005D3B A2[8B740000]        <1> 	mov	[mdev], al ; 0
  2349                              <1> 	     	; clr mntd / no, clear these
  2350 00005D40 A3[94740000]        <1>    	mov	[mnti], eax ; 11/01/2022 (eax = 0)
  2351                              <1> 	;mov	[mnti], ax ; 0
  2352                              <1>         	; clr mnti
  2353 00005D45 E9A4DDFFFF          <1>         jmp	sysret
  2354                              <1> 		; br sysreta / return
  2355                              <1> 
  2356                              <1> 	; 11/01/2022 - Retro UNIX 386 v1.2
  2357                              <1> 	;	(runix v2 fs inode numbers)
  2358                              <1> getspl: ; / get device number from a special file name
  2359 00005D4A E820ECFFFF          <1> 	call	namei
  2360                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2361                              <1> 		       ; ax = 0 -> file not found 	
  2362                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2363                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.2)
  2364 00005D4F 7305                <1> 	jnc	short getspl_0
  2365 00005D51 E93BFFFFFF          <1> 	jmp	sysmnt_err2
  2366                              <1> getspl_0:
  2367                              <1> 	;jz	error
  2368                              <1> 	;jc	error
  2369                              <1> 		; jsr r0,namei / get the i-number of the special file
  2370                              <1>                 ; br errora / no such file
  2371                              <1>         ; 11/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode numbers)
  2372 00005D56 6683E80A            <1> 	sub	ax, 10 ; fd0 inode number = 10, hd3 inode number = 15
  2373                              <1> 		      ;	i-number-10, 0 = fd0, 5 = hd3 
  2374                              <1> 	;sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2375                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2376                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2377 00005D5A 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2378                              <1> 	;jc	error
  2379                              <1> 		; ble errora / less than 0?  yes, error
  2380 00005D5C 6683F805            <1>         cmp	ax, 5 ; 5 = hd3
  2381                              <1> 		; cmp  r1,$9. / greater than 9  tap 7
  2382                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2383                              <1> 	;;ja	error
  2384                              <1> 		; bgt errora / yes, error
  2385                              <1> 	; 11/01/2022
  2386 00005D60 760F                <1> 	jna	short getspl_retn
  2387                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2388                              <1> ;iopen_retn:
  2389                              <1> ;	retn
  2390                              <1> 		; rts    r0 / return with device number in r1
  2391                              <1> sysmnt_err0:
  2392 00005D62 C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2392 00005D6A 0000                <1>
  2393 00005D6C E95DDDFFFF          <1> 	jmp	error
  2394                              <1> 
  2395                              <1> getspl_retn:
  2396                              <1> 	; 11/01/2022
  2397                              <1> 	; eax = Retro UNIX 386 v1 device number (0 to 5)
  2398                              <1> iopen_retn:
  2399 00005D71 C3                  <1> 	retn
  2400                              <1> 
  2401                              <1> 	; 11/02/2022
  2402                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2403                              <1> iopen:
  2404                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2405                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  2406                              <1> 	; 19/05/2015
  2407                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2408                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2409                              <1> 	;
  2410                              <1> 	; open file whose i-number is in r1
  2411                              <1> 	; 
  2412                              <1> 	; INPUTS ->
  2413                              <1> 	;    r1 - inode number
  2414                              <1> 	; OUTPUTS ->
  2415                              <1> 	;    file's inode in core	
  2416                              <1> 	;    r1 - inode number (positive)
  2417                              <1> 	;
  2418                              <1> 	; ((AX = R1))
  2419                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2420                              <1> 	;        
  2421                              <1> ; / open file whose i-number is in r1
  2422                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2423                              <1> ;		; tst r1 / write or read access?
  2424                              <1> ;       jnz	short iopen_2
  2425                              <1> ;		; blt 2f / write, go to 2f
  2426                              <1> ;	mov	dl, 2 ; read access
  2427                              <1> ;	call	access
  2428                              <1> ;       	; jsr r0,access; 2 
  2429                              <1> ;	; / get inode into core with read access
  2430                              <1> ;	; DL=2
  2431                              <1> ;iopen_0:
  2432                              <1> ;       cmp	ax, 40
  2433                              <1> ;		; cmp r1,$40. / is it a special file
  2434                              <1> ;       ja	short iopen_retn
  2435                              <1> ;		; bgt 3f / no. 3f
  2436                              <1> 
  2437                              <1> 	; 05/12/2021
  2438                              <1> 	; DL = 0 -> open for read
  2439                              <1> 	; DL = 1 -> open for write
  2440                              <1> 	; 11/02/2022
  2441                              <1> 	; DL = 2 -> create (open for write)
  2442                              <1> 		    ; (caller: syscreat)
  2443                              <1> 
  2444 00005D72 52                  <1> 	push	edx ; *
  2445                              <1> 
  2446                              <1> 	; set permission/mode flag for 'access' 
  2447                              <1> 	;	(DX = 100h -> IREAD, DX = 80h -> IWRITE)
  2448                              <1> 
  2449 00005D73 B601                <1> 	mov	dh, 1
  2450 00005D75 08D2                <1> 	or	dl, dl ; dl = 0, open for read	
  2451 00005D77 7404                <1> 	jz	short iopen_0 ; DX = IREAD (100h)
  2452                              <1> 	; dl = 1, open for write 
  2453                              <1> 	; or
  2454                              <1> 	; dl = 2, create (regular) file	; 11/02/2022
  2455 00005D79 FECE                <1> 	dec	dh
  2456 00005D7B B280                <1> 	mov	dl, 80h
  2457                              <1> 	; DX = IWRITE (80h)
  2458                              <1> iopen_0:
  2459                              <1> 	; 27/03/2021
  2460                              <1> 	;   EAX = inode number (in AX)
  2461                              <1> 	;    DX = access mode, 100h = read, 80h = write
  2462                              <1> 
  2463                              <1> 	; 24/06/2020 - Retro UNIX 386 v2	
  2464 00005D7D E86CF7FFFF          <1> 	call	access
  2465                              <1> 		; jsr r0,access; 1 / get inode in core
  2466                              <1> 	
  2467                              <1> 	; 27/03/2021
  2468                              <1> 	; DX return value from 'access' subroutine
  2469                              <1> 	;    may be 100h, 20h, 04h for DX = 100h (IREAD) input
  2470                              <1> 	;	     80h, 10h, 02h for DX = 80h (IWRITE) input
  2471                              <1> 
  2472                              <1> 	; 05/12/2021
  2473 00005D82 5A                  <1> 	pop	edx ; * ; dl = 0 -> open for read
  2474                              <1> 			; dl = 1 -> open for write
  2475                              <1> 			; 11/02/2022
  2476                              <1> 			; dl = 2 -> create (regular) file
  2477                              <1> 			;	   (open for writing)
  2478                              <1> 	; 24/06/2020
  2479 00005D83 8A0D[45700000]      <1> 	mov	cl, [i.flgs+1]
  2480                              <1> 
  2481 00005D89 F6C180              <1> 	test	cl, 80h		; regular file ?
  2482 00005D8C 752F                <1> 	jnz	short iopen_1	; yes ; 05/12/2021
  2483 00005D8E F6C120              <1> 	test	cl, 20h 	; device file ?
  2484                              <1> 	;jnz	short iopen_2	; yes
  2485                              <1> 	; 11/02/2022
  2486 00005D91 7414                <1> 	jz	short iopen_invf ; no, invalid file/inode !
  2487                              <1> 	; device file/inode
  2488 00005D93 F6C202              <1> 	test	dl, 2 ; create file ?
  2489 00005D96 742F                <1> 	jz	short iopen_2	; device file r/w (dl=0 or dl=1)
  2490                              <1> 	; an attempt to create a file 
  2491                              <1> 	; whith name of existing device file in same directory!
  2492                              <1> iopen_pdnd:
  2493 00005D98 C705[1C750000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; 11
  2493 00005DA0 0000                <1>
  2494                              <1> 				; 'permission denied !' error
  2495                              <1> iopen_err:
  2496 00005DA2 E927DDFFFF          <1> 	jmp	error
  2497                              <1> iopen_invf:
  2498                              <1> ; temporary - 15/02/2022
  2499 00005DA7 B046                <1> mov al, 'F'
  2500 00005DA9 B44E                <1> mov ah, 4Eh
  2501 00005DAB 66A300800B00        <1> mov [0B8000h], ax
  2502                              <1> 
  2503                              <1> 	; invalid inode (flags)
  2504 00005DB1 C705[1C750000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  2504 00005DB9 0000                <1>
  2505 00005DBB EBE5                <1> 	jmp	short iopen_err
  2506                              <1> 
  2507                              <1> iopen_1:
  2508                              <1> 	; 05/12/2021
  2509                              <1> 	; (If open mode is 'write' and the file/inode is a directory,
  2510                              <1> 	;  open request will/must be rejected.)
  2511                              <1> 	;
  2512                              <1> 	; (If inode is a regular file and it is not a directory,
  2513                              <1> 	; there is nothing to do here, we need to return to 'sysopen'
  2514                              <1> 	; for completing the rest of file opening procedure.) 
  2515                              <1> 	
  2516 00005DBD F6C140              <1> 	test	cl, 40h	; directory ?
  2517 00005DC0 74AF                <1> 	jz	short iopen_retn ; no
  2518                              <1> 	
  2519 00005DC2 20D2                <1> 	and	dl, dl ; open mode is 1 (write) 
  2520                              <1> 	;jz	short iopen_retn ; no
  2521                              <1> 	; 11/02/2022
  2522                              <1> 	; open mode 1 (write) or 2 (create)
  2523 00005DC4 75D2                <1> 	jnz	short iopen_pdnd ; 'permission denied !' error
  2524                              <1> ;iopen_retn:
  2525 00005DC6 C3                  <1> 	retn
  2526                              <1> 
  2527                              <1> 	; !!!	
  2528                              <1> 	; 'sysopen' for writing
  2529                              <1> 	;	 is not applicable for directories
  2530                              <1> 	; (Directory entries must be created or deleted by
  2531                              <1> 	; relevant system calls.)
  2532                              <1> 
  2533                              <1> 	;;mov	dword [u.error], ERR_DIR_ACCESS ; 11
  2534                              <1> 	;mov	dword [u.error], ERR_PERM_DENIED ; 11
  2535                              <1> 	;			; 'permission denied !' error
  2536                              <1> 	;;jmp	error
  2537                              <1> 	;jmp	short iopen_err
  2538                              <1> 
  2539                              <1> ;iopen_retn:
  2540                              <1> ;	retn
  2541                              <1> 
  2542                              <1> iopen_2:
  2543                              <1> 	;push	ax
  2544                              <1> 	;	; mov r1,-(sp) / yes, figure out
  2545                              <1> 	;movzx	ebx, al
  2546                              <1> 	;shl	bx, 2
  2547                              <1> 	;	; asl r1
  2548                              <1>         ;add	ebx, iopen_1 - 4
  2549                              <1> 	;jmp	dword [ebx]
  2550                              <1>         ;	; jmp *1f-2(r1) / which one and transfer to it
  2551                              <1> 	
  2552                              <1> 	; 05/12/2021
  2553 00005DC7 50                  <1> 	push	eax ; save inode number
  2554                              <1> 	; device file
  2555 00005DC8 BB[E45D0000]        <1> 	mov	ebx, iopen_4
  2556 00005DCD 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2557 00005DD0 720E                <1> 	jb	short iopen_3 ; null
  2558 00005DD2 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2559 00005DD5 7709                <1> 	ja	short iopen_3 ; null	
  2560                              <1> 	; convert v2 inode number to v1 device inode number
  2561 00005DD7 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2562 00005DD9 89C1                <1> 	mov	ecx, eax
  2563 00005DDB C0E102              <1> 	shl	cl, 2 ; * 4
  2564 00005DDE 01CB                <1> 	add	ebx, ecx
  2565                              <1> iopen_3:
  2566 00005DE0 FEC2                <1> 	inc	dl ; 1 = read, 2 = write
  2567 00005DE2 FF23                <1> 	jmp	dword [ebx]	
  2568                              <1> 		; jmp *1f-2(r1)
  2569                              <1> ;iopen_1: ; 1:
  2570                              <1> iopen_4:
  2571 00005DE4 [1B580000]          <1> 	dd	null ; 05/12/2021
  2572 00005DE8 [345E0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2573                              <1>  		 ;otty / tty ; r1=2
  2574                              <1>         	 ;oppt / ppt ; r1=4
  2575 00005DEC [DE5E0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2576                              <1> 		 ;sret / mem ; r1=6
  2577                              <1> 		 ;sret / rf0
  2578                              <1>         	 ;sret / rk0
  2579                              <1>         	 ;sret / tap0
  2580                              <1>         	 ;sret / tap1
  2581                              <1>         	 ;sret / tap2
  2582                              <1>         	 ;sret / tap3
  2583                              <1>         	 ;sret / tap4
  2584                              <1>         	 ;sret / tap5
  2585                              <1>         	 ;sret / tap6
  2586                              <1>         	 ;sret / tap7
  2587 00005DF0 [DE5E0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2588 00005DF4 [DE5E0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2589 00005DF8 [DE5E0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2590 00005DFC [DE5E0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2591 00005E00 [DE5E0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2592 00005E04 [DE5E0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2593                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2594 00005E08 [DE5E0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2595 00005E0C [435E0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2596                              <1> 		 ;ocvt / tty0
  2597 00005E10 [435E0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2598                              <1> 		 ;ocvt / tty1
  2599 00005E14 [435E0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2600                              <1> 		 ;ocvt / tty2
  2601 00005E18 [435E0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2602                              <1> 		 ;ocvt / tty3
  2603 00005E1C [435E0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2604                              <1> 		 ;ocvt / tty4
  2605 00005E20 [435E0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2606                              <1> 		 ;ocvt / tty5
  2607 00005E24 [435E0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2608                              <1> 		 ;ocvt / tty6
  2609 00005E28 [435E0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2610                              <1> 		 ;ocvt / tty7
  2611 00005E2C [435E0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2612                              <1> 		 ;error / crd
  2613 00005E30 [435E0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2614                              <1> 
  2615                              <1> ;iopen_2: ; 2: / check open write access
  2616                              <1> ;	neg	ax
  2617                              <1> ;		; neg r1 / make inode number positive
  2618                              <1> ;	mov	dl, 1 ; write access
  2619                              <1> ;	call	access
  2620                              <1> ;		; jsr r0,access; 1 / get inode in core
  2621                              <1> ;	; DL=1
  2622                              <1> ;	test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2623                              <1> ;		;bit $40000,i.flgs / is it a directory?
  2624                              <1> ;	jz	short iopen_0
  2625                              <1> ;	;mov	[u.error], ERR_DIR_ACCESS
  2626                              <1> ;	;jmp	error ; permission denied !
  2627                              <1> ;	jmp	sysmnt_err0
  2628                              <1> ;	;;jnz	error		
  2629                              <1> ;      		; bne 2f / yes, transfer (error)
  2630                              <1> ;       ;;jmp     short iopen_0
  2631                              <1> ;	;cmp	ax, 40
  2632                              <1> ;		; cmp r1,$40. / no, is it a special file?
  2633                              <1> ;        ;ja	short iopen_2
  2634                              <1> ;		; bgt 3f / no, return
  2635                              <1> ;	;push	ax
  2636                              <1> ;		; mov r1,-(sp) / yes
  2637                              <1> ;	;movzx	ebx, al
  2638                              <1> ;	;shl	bx, 1
  2639                              <1> ;		; asl r1
  2640                              <1> ;	;add	ebx, ipen_3 - 2
  2641                              <1> ;	;jmp	dword [ebx]
  2642                              <1> ;		; jmp *1f-2(r1) / figure out 
  2643                              <1> ;			; / which special file it is and transfer
  2644                              <1> ;iopen_3: ; 1:
  2645                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2646                              <1> ; 		 ;otty / tty ; r1=2
  2647                              <1> ;        	 ;leadr / ppt ; r1=4
  2648                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2649                              <1> ;		 ;sret / mem ; r1=6
  2650                              <1> ;		 ;sret / rf0
  2651                              <1> ;        	 ;sret / rk0
  2652                              <1> ;        	 ;sret / tap0
  2653                              <1> ;        	 ;sret / tap1
  2654                              <1> ;        	 ;sret / tap2
  2655                              <1> ;        	 ;sret / tap3
  2656                              <1> ;        	 ;sret / tap4
  2657                              <1> ;        	 ;sret / tap5
  2658                              <1> ;        	 ;sret / tap6
  2659                              <1> ;        	 ;sret / tap7
  2660                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2661                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2662                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2663                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2664                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2665                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2666                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2667                              <1> ;	;dd	ejec ; lpr, AX = 9  (runix)
  2668                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2669                              <1> ;		 ;ocvt / tty0
  2670                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2671                              <1> ;		 ;ocvt / tty1
  2672                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2673                              <1> ;		 ;ocvt / tty2
  2674                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2675                              <1> ;		 ;ocvt / tty3
  2676                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2677                              <1> ;		 ;ocvt / tty4
  2678                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2679                              <1> ;		 ;ocvt / tty5
  2680                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2681                              <1> ;		 ;ocvt / tty6
  2682                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2683                              <1> ;		 ;ocvt / tty7
  2684                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2685                              <1> ;		 ;/ ejec / lpr
  2686                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2687                              <1> 
  2688                              <1> otty: ;/ open console tty for reading or writing
  2689                              <1> 	; 09/02/2022
  2690                              <1> 	; 06/02/2022
  2691                              <1> 	; 08/01/2022
  2692                              <1> 	; 01/01/2022
  2693                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2694                              <1> 	; 16/11/2015
  2695                              <1> 	; 12/11/2015
  2696                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2697                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2698                              <1> 	; 16/07/2013
  2699                              <1> 	; Retro UNIX 8086 v1 modification:
  2700                              <1> 	;  If a tty is open for read or write by
  2701                              <1> 	;     a process (u.uno), only same process can open
  2702                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2703                              <1> 	;
  2704                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2705                              <1> 	;
  2706                              <1> 
  2707 00005E34 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2708 00005E3B 8A83[C3700000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2709                              <1> 	; 13/01/2014
  2710                              <1> 	;jmp	short ottyp
  2711                              <1> 	; 06/02/2022
  2712 00005E41 EB04                <1> 	jmp	short otty_0
  2713                              <1> ocvt:
  2714 00005E43 2C0A                <1> 	sub	al, 10
  2715                              <1> ;ottyp:	; (call from sysstty)
  2716                              <1> 	; 08/01/2022
  2717 00005E45 31DB                <1> 	xor	ebx, ebx
  2718                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2719                              <1> otty_0:
  2720                              <1> 	; 09/02/2022
  2721                              <1> 	; INPUT:
  2722                              <1> 	;	DL=1 for read, DL=2 for write, DL=0 for sysstty
  2723                              <1> 	;
  2724                              <1> 	; 08/01/2022
  2725                              <1> 	; 01/01/2022
  2726                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2727                              <1> 	; 16/11/2015
  2728                              <1> 	; 12/11/2015
  2729                              <1> 	; 18/05/2015 (32 bit modifications)
  2730                              <1> 	; 06/12/2013 - 13/07/2014
  2731 00005E47 88C6                <1> 	mov	dh, al ; tty number
  2732                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2733                              <1> 	; 08/01/2022
  2734 00005E49 88C3                <1> 	mov	bl, al
  2735 00005E4B D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2736                              <1> 	; 26/01/2014	
  2737 00005E4D 81C3[D46F0000]      <1> 	add 	ebx, ttyl
  2738 00005E53 668B0B              <1> 	mov 	cx, [ebx]
  2739                              <1> 		   ; CL = lock value (0 or process number)
  2740                              <1> 		   ; CH = open count 
  2741 00005E56 20C9                <1> 	and 	cl, cl
  2742                              <1> 	; 13/01/2014
  2743                              <1> 	;jz 	short otty_ret
  2744                              <1> 	; 05/12/2021
  2745 00005E58 7439                <1> 	jz 	short ottys_0
  2746                              <1> 	;
  2747                              <1> 	; 16/11/2015
  2748 00005E5A 3A0D[F9740000]      <1> 	cmp 	cl, [u.uno]
  2749 00005E60 7464                <1> 	je	short ottys_3
  2750                              <1> 	;
  2751 00005E62 0FB6D9              <1> 	movzx 	ebx, cl ; the process which has locked the tty
  2752 00005E65 D0E3                <1> 	shl 	bl, 1
  2753 00005E67 668B83[82700000]    <1> 	mov 	ax, [ebx+p.pid-2]
  2754                              <1> 	;movzx 	ebx, byte [u.uno]
  2755 00005E6E 8A1D[F9740000]      <1> 	mov	bl, [u.uno]
  2756 00005E74 D0E3                <1> 	shl 	bl, 1
  2757 00005E76 663B83[A2700000]    <1> 	cmp 	ax, [ebx+p.ppid-2]
  2758 00005E7D 7447                <1> 	je 	short ottys_3  ; 16/11/2015
  2759                              <1> 	;
  2760                              <1> 	; the tty is locked by another process
  2761                              <1> 	; except the parent process (p.ppid)
  2762                              <1>         ; 09/02/2022
  2763                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2764                              <1> 	;		; permission denied ! error
  2765                              <1> otty_err: ; 13/01/2014
  2766                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2767                              <1> 	;;jnz	error
  2768                              <1> 	; 05/12/2021
  2769                              <1> 	;jz	short otty_stc_retn
  2770                              <1> 	;jmp	error
  2771                              <1> 	; 09/02/2022
  2772 00005E7F 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2773 00005E82 725B                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2774                              <1> 	; iopen (dl=1 or dl=2)
  2775 00005E84 C705[1C750000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2775 00005E8C 0000                <1>
  2776                              <1> 			; permission denied ! error
  2777 00005E8E E93BDCFFFF          <1> 	jmp	error
  2778                              <1> ;otty_stc_retn:
  2779                              <1> 	;stc
  2780                              <1> 	;retn
  2781                              <1> ottys_0:
  2782                              <1> 	; 05/12/2021
  2783                              <1> otty_ret:
  2784                              <1> 	; 13/01/2014
  2785 00005E93 80FE07              <1> 	cmp 	dh, 7
  2786 00005E96 7624                <1> 	jna	short ottys_2
  2787                              <1> 	; 16/11/2015
  2788                              <1> com_port_check:
  2789 00005E98 BE[F26F0000]        <1> 	mov	esi, com1p
  2790 00005E9D 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2791 00005EA0 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2792 00005EA2 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2793                              <1> ottys_1:
  2794                              <1> 	; 12/11/2015
  2795 00005EA3 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2796 00005EA6 7714                <1> 	ja	short com_port_ready
  2797                              <1> 	;
  2798                              <1> 	; 09/02/2022
  2799 00005EA8 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2800 00005EAB 7232                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2801 00005EAD C705[1C750000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2801 00005EB5 0000                <1>
  2802                              <1> 			   ; device not ready ! error
  2803                              <1> 	;jmp	short otty_err
  2804 00005EB7 E912DCFFFF          <1> 	jmp	error	 
  2805                              <1> com_port_ready:
  2806                              <1> ottys_2:
  2807 00005EBC 08C9                <1> 	or	cl, cl  ; cl = lock/owner, ch = open count
  2808 00005EBE 7506                <1> 	jnz	short ottys_3
  2809 00005EC0 8A0D[F9740000]      <1> 	mov	cl, [u.uno]
  2810                              <1> ottys_3:
  2811 00005EC6 FEC5                <1> 	inc 	ch
  2812 00005EC8 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2813                              <1> 	; 06/12/2013
  2814 00005ECB FEC6                <1> 	inc	dh ; tty number + 1
  2815 00005ECD BB[DE740000]        <1> 	mov	ebx, u.ttyp
  2816                              <1> 	; 13/01/2014
  2817                              <1> 	;test	dl, 2 ; open for read sign
  2818                              <1> 	;jnz	short ottys_4
  2819                              <1> 	; 05/12/2021
  2820                              <1> 	;test	dl, 2
  2821                              <1> 	;jz	short ottys_4 ; open for read
  2822                              <1> 	; 01/01/2022
  2823 00005ED2 F6C201              <1> 	test	dl, 1
  2824 00005ED5 7501                <1> 	jnz	short ottys_4 ; open for read (dl=1)
  2825                              <1> 	; dl=2 (open for write) or dl=0 (sysstty)
  2826 00005ED7 43                  <1> 	inc	ebx
  2827                              <1> ottys_4:
  2828                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2829 00005ED8 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2830                              <1> 	; 09/02/2022
  2831 00005EDA 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2832 00005EDC 7401                <1> 	jz	short iclose_retn
  2833                              <1> sret:
  2834                              <1> 	;pop 	ax
  2835                              <1> 	; 05/12/2021
  2836 00005EDE 58                  <1> 	pop	eax
  2837                              <1> otty_retn:	; 09/02/2022
  2838                              <1> iclose_retn:	
  2839 00005EDF C3                  <1> 	retn
  2840                              <1> 
  2841                              <1> 	;
  2842                              <1> 	; Original UNIX v1 'otty' routine:
  2843                              <1> 	;	
  2844                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2845                              <1>         ;                 / reader status reg
  2846                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2847                              <1>         ;                 / punch status reg
  2848                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2849                              <1>         ;                          / console tty buffer
  2850                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2851                              <1>         ;            / console tty
  2852                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2853                              <1>         ;             / buffer header
  2854                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2855                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2856                              <1>         ;                 / tty
  2857                              <1>         ;br     sret / ?
  2858                              <1> ;sret:
  2859                              <1> 		;clr *$ps / set processor priority to zero
  2860                              <1> ;	pop	ax
  2861                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2862                              <1> ;3:
  2863                              <1> ;	retn
  2864                              <1>         	;rts r0
  2865                              <1> 	
  2866                              <1> ;ocvt:	; < open tty >
  2867                              <1> 	; 13/01/2014
  2868                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2869                              <1> 	; 24/09/2013 consistency check -> ok
  2870                              <1> 	; 16/09/2013
  2871                              <1> 	; 03/09/2013
  2872                              <1> 	; 27/08/2013
  2873                              <1> 	; 16/08/2013
  2874                              <1> 	; 16/07/2013
  2875                              <1> 	; 27/05/2013
  2876                              <1> 	; 21/05/2013
  2877                              <1> 	;
  2878                              <1> 	; Retro UNIX 8086 v1 modification !
  2879                              <1> 	; 
  2880                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2881                              <1> 	;		(exactly different than this one)
  2882                              <1> 	;	was in 'u9.s' file.
  2883                              <1> 	;
  2884                              <1> 	; 16/07/2013
  2885                              <1> 	; Retro UNIX 8086 v1 modification:
  2886                              <1> 	;  If a tty is open for read or write by
  2887                              <1> 	;     a process (u.uno), only same process can open
  2888                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2889                              <1> 	;
  2890                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2891                              <1> 
  2892                              <1> 	; 16/09/2013
  2893                              <1> 	; sub 	al, 10
  2894                              <1> 	
  2895                              <1> 	; 06/12/2013
  2896                              <1> 	;cmp	al, 7
  2897                              <1>         ;jna	short ottyp
  2898                              <1> 	; 13/01/2014
  2899                              <1> 	;jmp	short ottyp
  2900                              <1> 
  2901                              <1> ;oppt: / open paper tape for reading or writing
  2902                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2903                              <1> ;        tstb   pptiflg / is file already open
  2904                              <1> ;        bne    2f / yes, branch
  2905                              <1> ;1:
  2906                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2907                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2908                              <1> ;               br .+4 / for paper tape input and place in free list
  2909                              <1> ;        br     1b
  2910                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2911                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2912                              <1> ;        br     sret
  2913                              <1> ;2:
  2914                              <1> ;        jmp    error / file already open
  2915                              <1> 
  2916                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2917                              <1> iclose:
  2918                              <1> 	; 09/02/2022
  2919                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2920                              <1> 	; 10/04/2021
  2921                              <1> 	; 08/04/2021
  2922                              <1> 	; 04/04/2021 - Retro UNIX 386 v2
  2923                              <1> 	; 19/05/2015
  2924                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2925                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2926                              <1> 	;
  2927                              <1> 	; close file whose i-number is in r1
  2928                              <1> 	; 
  2929                              <1> 	; INPUTS ->
  2930                              <1> 	;    r1 - inode number
  2931                              <1> 	; OUTPUTS ->
  2932                              <1> 	;    file's inode in core	
  2933                              <1> 	;    r1 - inode number (positive)
  2934                              <1> 	;
  2935                              <1> 	; ((AX = R1))
  2936                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2937                              <1> 	;        
  2938                              <1> ;;/ close file whose i-number is in r1
  2939                              <1> ;	mov	dl, 2 ; 12/01/2014
  2940                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2941                              <1> ;		;tst r1 / test i-number
  2942                              <1> ;	;jnz	short iclose_2
  2943                              <1> ;		;blt 2f / if neg., branch
  2944                              <1> ;	jz	short iclose_0 ; 30/07/2013
  2945                              <1> ;	; 16/07/2013 
  2946                              <1> ;	neg	ax ; make it positive
  2947                              <1> ;	; 12/01/2014
  2948                              <1> ;	dec	dl ; dl = 1 (open for write)
  2949                              <1> ;iclose_0:
  2950                              <1> ;	cmp	ax, 40
  2951                              <1> ;		;cmp r1,$40. / is it a special file
  2952                              <1> ;       ja	short iclose_retn  ; 13/01/2014
  2953                              <1> ;		;bgt 3b / no, return
  2954                              <1> ;	; 12/01/2014
  2955                              <1> ;	; DL=2 -> special file was opened for reading
  2956                              <1> ;	; DL=1 -> special file was opened for writing
  2957                              <1> 
  2958                              <1> 	; 04/04/2021
  2959                              <1> 	; INPUT:
  2960                              <1> 	;	(e)ax = inode number
  2961                              <1> 	;	   dl = open mode
  2962                              <1> 	;		0 = control mode
  2963                              <1> 	;		1 = read
  2964                              <1> 	;		2 = write
  2965                              <1> 	; OUTPUT:
  2966                              <1> 	;	none
  2967                              <1> 	;	(if cf=1 -> eax = error code)
  2968                              <1> 	;	(if cf=0 -> ax = inode number)
  2969                              <1> 
  2970                              <1> 	; 10/04/2021
  2971                              <1>         ; Modified registers: ebx, ecx, edx, esi, edi, (ebp) 
  2972                              <1> 
  2973                              <1> 	; 05/12/2021
  2974                              <1> 	; 08/04/2021
  2975                              <1> 
  2976 00005EE0 52                  <1> 	push	edx
  2977 00005EE1 E81EF5FFFF          <1> 	call	iget
  2978 00005EE6 5A                  <1> 	pop	edx 
  2979                              <1> 
  2980 00005EE7 8A0D[45700000]      <1> 	mov	cl, [i.flgs+1]
  2981                              <1> 
  2982                              <1> 	; if i.flgs bit 15 is 1, it is regular file 
  2983                              <1> 	;test	byte [i.flgs+1], 80h ; is it a special file?
  2984 00005EED F6C180              <1> 	test	cl, 80h ; is it a special file?
  2985 00005EF0 75ED                <1> 	jnz	short iclose_retn ; no
  2986                              <1> 
  2987                              <1> 	;; inode flags - bit 13 must be 1 
  2988                              <1> 	;test	cl, 20h ; is it a valid device inode
  2989                              <1> 	;jz	short iclose_retn ; no ; 19/01/2022
  2990                              <1> 	
  2991                              <1> 	;push	ax
  2992                              <1> 	;	;mov r1,-(sp) / yes, save r1 on stack
  2993                              <1> 	;movzx	ebx, al
  2994                              <1> 	;shl	bx, 2
  2995                              <1> 	;	; asl r1
  2996                              <1> 	;add	ebx, iclose_1 - 4
  2997                              <1> 	;jmp	dword [ebx]
  2998                              <1> 	;	; jmp *1f-2(r1) / compute jump address and transfer
  2999                              <1> 
  3000                              <1> 	; 05/12/2021
  3001 00005EF2 50                  <1> 	push	eax ; save inode number
  3002                              <1> 	; device file
  3003 00005EF3 BB[0D5F0000]        <1> 	mov	ebx, iclose_1
  3004 00005EF8 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  3005 00005EFB 720E                <1> 	jb	short iclose_0
  3006 00005EFD 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  3007 00005F00 7709                <1> 	ja	short iclose_0
  3008                              <1> 	; convert v2 inode number to v1 device inode number
  3009 00005F02 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  3010 00005F04 89C1                <1> 	mov	ecx, eax
  3011 00005F06 C0E102              <1> 	shl	cl, 2 ; * 4
  3012 00005F09 01CB                <1> 	add	ebx, ecx
  3013                              <1> iclose_0:
  3014 00005F0B FF23                <1> 	jmp	dword [ebx]	
  3015                              <1> 		 ; jmp *1f-2(r1)
  3016                              <1> iclose_1: ; 1:
  3017 00005F0D [1B580000]          <1> 	dd	null ; 05/12/2021
  3018 00005F11 [5D5F0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  3019 00005F15 [B85F0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  3020 00005F19 [B85F0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  3021 00005F1D [B85F0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  3022 00005F21 [B85F0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  3023 00005F25 [B85F0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  3024 00005F29 [B85F0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  3025 00005F2D [B85F0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  3026 00005F31 [B85F0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  3027                              <1> 	;dd	error; lpr, AX = 9 (error!)
  3028                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  3029 00005F35 [6C5F0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  3030 00005F39 [6C5F0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  3031 00005F3D [6C5F0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  3032 00005F41 [6C5F0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  3033 00005F45 [6C5F0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  3034 00005F49 [6C5F0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  3035 00005F4D [6C5F0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  3036 00005F51 [6C5F0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  3037 00005F55 [6C5F0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  3038 00005F59 [6C5F0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  3039                              <1> 
  3040                              <1> 	; 1:
  3041                              <1> 	;        ctty   / tty
  3042                              <1> 	;        cppt   / ppt
  3043                              <1> 	;        sret   / mem
  3044                              <1> 	;        sret   / rf0
  3045                              <1> 	;        sret   / rk0
  3046                              <1> 	;        sret   / tap0
  3047                              <1> 	;        sret   / tap1
  3048                              <1> 	;        sret   / tap2
  3049                              <1> 	;        sret   / tap3
  3050                              <1> 	;        sret   / tap4
  3051                              <1> 	;        sret   / tap5
  3052                              <1> 	;        sret   / tap6
  3053                              <1> 	;        sret   / tap7
  3054                              <1> 	;        ccvt   / tty0
  3055                              <1> 	;        ccvt   / tty1
  3056                              <1> 	;        ccvt   / tty2
  3057                              <1> 	;        ccvt   / tty3
  3058                              <1> 	;        ccvt   / tty4
  3059                              <1> 	;        ccvt   / tty5
  3060                              <1> 	;        ccvt   / tty6
  3061                              <1> 	;        ccvt   / tty7
  3062                              <1> 	;        error / crd
  3063                              <1> 
  3064                              <1> ;iclose_2: ; 2: / negative i-number
  3065                              <1> 	;neg	ax
  3066                              <1> 		;neg r1 / make it positive
  3067                              <1> 	;cmp	ax, 40
  3068                              <1> 		;cmp r1,$40. / is it a special file?
  3069                              <1>         ;ja	short @b
  3070                              <1> 		;bgt 3b / no. return
  3071                              <1> 	;push	ax
  3072                              <1> 		;mov r1,-(sp)
  3073                              <1> 	;movzx	ebx, al
  3074                              <1> 	;shl	bx, 1
  3075                              <1> 		;asl r1 / yes. compute jump address and transfer
  3076                              <1> 	;add	ebx, iclose_3 - 2
  3077                              <1> 	;jmp	dword [ebx]
  3078                              <1> 		;jmp *1f-2(r1) / figure out 
  3079                              <1> ;iclose_3:
  3080                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  3081                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  3082                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  3083                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  3084                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  3085                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  3086                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  3087                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  3088                              <1> 	;;dd	sret ; lpr, AX = 9	
  3089                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  3090                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  3091                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3092                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3093                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3094                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3095                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3096                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3097                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3098                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3099                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3100                              <1> 	
  3101                              <1> 	;1:
  3102                              <1> 	;      	ctty   / tty
  3103                              <1> 	;       leadr  / ppt
  3104                              <1> 	;       sret   / mem
  3105                              <1> 	;       sret   / rf0
  3106                              <1> 	;       sret   / rk0
  3107                              <1> 	;       sret   / tap0
  3108                              <1> 	;       sret   / tap1
  3109                              <1> 	;       sret   / tap2
  3110                              <1> 	;       sret   / tap3
  3111                              <1> 	;       sret   / tap4
  3112                              <1> 	;       sret   / tap5
  3113                              <1> 	;       sret   / tap6
  3114                              <1> 	;       sret   / tap7
  3115                              <1> 	;       ccvt   / tty0
  3116                              <1> 	;       ccvt   / tty1
  3117                              <1> 	;       ccvt   / tty2
  3118                              <1> 	;       ccvt   / tty3
  3119                              <1> 	;       ccvt   / tty4
  3120                              <1> 	;       ccvt   / tty5
  3121                              <1> 	;       ccvt   / tty6
  3122                              <1> 	;       ccvt   / tty7
  3123                              <1> 	;/       ejec / lpr
  3124                              <1> 
  3125                              <1> ctty: ; / close console tty
  3126                              <1> 	; 09/02/2022
  3127                              <1> 	; 06/02/2022
  3128                              <1> 	; 08/01/2022
  3129                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3130                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3131                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3132                              <1> 	;
  3133                              <1> 	; Retro UNIX 8086 v1 modification !
  3134                              <1> 	; (DL = 2 -> it is open for reading)
  3135                              <1> 	; (DL = 1 -> it is open for writing)
  3136                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3137                              <1> 	;
  3138                              <1> 	; 06/12/2013
  3139 00005F5D 0FB61D[F9740000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3140 00005F64 8A83[C3700000]      <1>         mov     al, [ebx+p.ttyc-1]
  3141                              <1> 	; 13/01/2014
  3142                              <1> 	;jmp	short cttyp
  3143                              <1> 	; 06/02/2022
  3144 00005F6A EB04                <1> 	jmp	short ctty_0
  3145                              <1> ccvt:
  3146 00005F6C 2C0A                <1> 	sub 	al, 10
  3147                              <1> cttyp:
  3148                              <1> 	; 08/01/2022
  3149 00005F6E 31DB                <1> 	xor	ebx, ebx
  3150                              <1> ctty_0:		; 06/02/2022
  3151                              <1> 	; 09/02/2022
  3152                              <1> 	;    DL=2 -> open for writing
  3153                              <1> 	;    DL=1 -> open for reading
  3154                              <1> 	;    DL=0 -> open for sysstty system call	
  3155                              <1> 	; 08/01/2022
  3156                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3157                              <1> 	; 18/05/2015 (32 bit modifications)
  3158                              <1> 	; 16/08/2013 - 26/01/2014
  3159                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3160                              <1> 	; 08/01/2022
  3161 00005F70 88C3                <1> 	mov	bl, al
  3162 00005F72 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3163                              <1> 	; 26/01/2014
  3164 00005F74 81C3[D46F0000]      <1> 	add 	ebx, ttyl
  3165 00005F7A 88C6                <1> 	mov 	dh, al ; tty number
  3166 00005F7C 668B03              <1> 	mov 	ax, [ebx]
  3167                              <1> 		   ; AL = lock value (0 or process number)
  3168                              <1> 		   ; AH = open count 
  3169 00005F7F 20E4                <1> 	and 	ah, ah
  3170 00005F81 7514                <1> 	jnz	short ctty_ret
  3171                              <1> 	; 09/02/2022
  3172 00005F83 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3173 00005F86 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3174                              <1> 	; iclose (dl=1 or dl=2)
  3175 00005F88 C705[1C750000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3175 00005F90 0000                <1>
  3176                              <1> 			; device not open ! error
  3177                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3178 00005F92 E937DBFFFF          <1> 	jmp	error
  3179                              <1> 	; 26/01/2014
  3180                              <1> ctty_ret:
  3181 00005F97 FECC                <1> 	dec 	ah ; decrease open count
  3182 00005F99 7502                <1> 	jnz	short ctty_1
  3183 00005F9B 30C0                <1> 	xor	al, al ; unlock/free tty
  3184                              <1> ctty_1:
  3185 00005F9D 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3186                              <1> 	;
  3187 00005FA0 BB[DE740000]        <1> 	mov	ebx, u.ttyp
  3188                              <1> 	;;test	dl, 1 ; open for write sign
  3189                              <1> 	;;jz	short ctty_2
  3190                              <1> 	; 05/12/2021
  3191                              <1> 	;test	dl, 2 ; open for write sign
  3192                              <1> 	;jz	short ctty_2	
  3193                              <1> 	; 09/02/2022
  3194 00005FA5 F6C201              <1> 	test	dl, 1 ; open for read sign
  3195 00005FA8 7501                <1> 	jnz	short ctty_2
  3196                              <1> 	; open for write (dl=0 or dl=2)
  3197 00005FAA 43                  <1> 	inc	ebx
  3198                              <1> ctty_2:
  3199 00005FAB FEC6                <1> 	inc	dh ; tty number + 1
  3200 00005FAD 3A33                <1> 	cmp	dh, [ebx]
  3201                              <1> 	;jne	short cret
  3202 00005FAF 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3203                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3204 00005FB1 C60300              <1> 	mov	byte [ebx], 0
  3205                              <1> ctty_3:
  3206                              <1> 	; 09/02/2022
  3207 00005FB4 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3208 00005FB6 7401                <1> 	jz	short ctty_4
  3209                              <1> cret:
  3210                              <1> 	;pop	ax
  3211                              <1> 	; 05/12/2021
  3212 00005FB8 58                  <1> 	pop	eax
  3213                              <1> ctty_stc_retn:	; 09/02/2022
  3214                              <1> ctty_4:
  3215 00005FB9 C3                  <1> 	retn
  3216                              <1> 
  3217                              <1> ;ctty_err: ; 13/01/2014
  3218                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3219                              <1> ;	jnz	error
  3220                              <1> ;	stc
  3221                              <1> ;	retn
  3222                              <1> 
  3223                              <1> 	; Original UNIX v1 'ctty' routine:
  3224                              <1> 	;	
  3225                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3226                              <1> 	;		;/ point r5 to the console tty buffer
  3227                              <1>         ;decb   (r5) / dec number of processes using console tty
  3228                              <1>         ;br     sret / return via sret
  3229                              <1> 
  3230                              <1> ;ccvt:	; < close tty >
  3231                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3232                              <1> 	;
  3233                              <1> 	; Retro UNIX 8086 v1 modification !
  3234                              <1> 	; 
  3235                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3236                              <1> 	;		(exactly different than this one)
  3237                              <1> 	;	was in 'u9.s' file.
  3238                              <1> 	;
  3239                              <1> 	; DL = 2 -> it is open for reading
  3240                              <1> 	; DL = 1 -> it is open for writing
  3241                              <1> 	;
  3242                              <1> 	; 17/09/2013
  3243                              <1> 	;sub 	al, 10
  3244                              <1> 	;cmp	al, 7
  3245                              <1> 	;jna	short cttyp
  3246                              <1> 	; 13/01/2014
  3247                              <1> 	;jmp	short cttyp
  3248                              <1> 
  3249                              <1> ;cppt: / close paper tape
  3250                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3251                              <1> ;1:
  3252                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3253                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3254                              <1> ;                          / and assign to free list
  3255                              <1> ;               br sret
  3256                              <1> ;        br     1b
  3257                              <1> 
  3258                              <1> ;ejec:	
  3259                              <1> ;	jmp	error
  3260                              <1> ;/ejec:
  3261                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3262                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3263                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3264                              <1> ;/       br     sret / return to caller via 'sret'
  2079                                  %include 'u8.s'      ; 11/06/2015
  2080                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2081                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2082                              <1> ; ****************************************************************************
  2083                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  2084                              <1> ; Last Modification: 12/02/2022
  2085                              <1> ; ----------------------------------------------------------------------------
  2086                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2087                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2088                              <1> ;
  2089                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2090                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2091                              <1> ; <Bell Laboratories (17/3/1972)>
  2092                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2093                              <1> ;
  2094                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2095                              <1> ;
  2096                              <1> ; ****************************************************************************
  2097                              <1> 
  2098                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2099                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2100                              <1> ;; Word 1, byte 0 = device id
  2101                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2102                              <1> ;;          bit 9 = write bit
  2103                              <1> ;;	    bit 10 = read bit	  
  2104                              <1> ;;	    bit 12 = waiting to write bit	
  2105                              <1> ;;	    bit 13 = waiting to read bit
  2106                              <1> ;;	    bit 15 = inhibit bit
  2107                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2108                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2109                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2110                              <1> ;;
  2111                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2112                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2113                              <1> ;;
  2114                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2115                              <1> ;; Word 1, Byte 0 = device id
  2116                              <1> ;; Word 1, Byte 1 = (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 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2123                              <1> ;;
  2124                              <1> ;; Original UNIX v1 ->
  2125                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2126                              <1> ;; Original UNIX v1 -> 
  2127                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2128                              <1> ;;
  2129                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2130                              <1> ;;
  2131                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2132                              <1> ;;          0 = fd0
  2133                              <1> ;;	    1 = fd1
  2134                              <1> ;;	    2 = hd0
  2135                              <1> ;;	    3 = hd1
  2136                              <1> ;;	    4 = hd2
  2137                              <1> ;;	    5 = hd3
  2138                              <1> 
  2139                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2140                              <1> 
  2141                              <1> 	; 08/02/2022
  2142                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2143                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2144                              <1> 	; 26/04/2013
  2145                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2146                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2147                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2148                              <1> 
  2149                              <1> 	; 08/02/2022
  2150                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2151                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2152                              <1> 	; 26/04/2013
  2153                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2154                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2155                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2156                              <1> 
  2157                              <1> bread: 
  2158                              <1> 	; 08/02/2022
  2159                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2160                              <1> 	; 14/07/2015
  2161                              <1> 	; 10/07/2015
  2162                              <1> 	; 09/06/2015
  2163                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2164                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2165                              <1> 	;	
  2166                              <1> 	; / read a block from a block structured device
  2167                              <1> 	;
  2168                              <1> 	; INPUTS ->
  2169                              <1> 	;    [u.fopf] points to the block number
  2170                              <1> 	;    CX = maximum block number allowed on device
  2171                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2172                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2173                              <1> 	;    [u.count] number of bytes to read in
  2174                              <1> 	; OUTPUTS ->
  2175                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2176                              <1> 	;    [u.fopf] points to next consecutive block to be read
  2177                              <1> 	;
  2178                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2179                              <1> 	;
  2180                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2181                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2182                              <1> 	;	is increased by 1. For example: If user/program request 
  2183                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2184                              <1> 	;  	the next block number just as 512 byte reading is done.
  2185                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2186                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2187                              <1> 	;       enough to keep byte position/offset of the disk), this
  2188                              <1> 	;	defect will not be corrected, user/program must request
  2189                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2190                              <1> 	;       for achieving correct result. In future version(s), 
  2191                              <1> 	;	this defect will be corrected by using different 
  2192                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2193                              <1> 
  2194                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2195                              <1> 			       ; / (only works on tape)
  2196                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2197                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2198                              <1> ;1:
  2199                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2200                              <1> 			    ; / maximum block # allowed on device
  2201                              <1> 		; jnb short @f
  2202                              <1> 		; bhis	1f / yes, 1f (error)
  2203                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2204                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2205                              <1> 		; mov (sp)+,r1 / return block # to r1
  2206                              <1> 		; inc r1 / bump block # to next consecutive block
  2207                              <1> 		; dec (sp) / "2-1-cold" on stack
  2208                              <1> 		; bgt 1b / 2-1-cold = 0? No, go back and read in next block
  2209                              <1> ;1:
  2210                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2211                              <1> 	;push	ecx ; **
  2212                              <1> 	; 26/04/2013
  2213                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2214 00005FBA 2C03                <1> 	sub	al, 3
  2215                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2216 00005FBC A2[1B750000]        <1> 	mov	[u.brwdev], al
  2217                              <1> 	; 09/06/2015
  2218                              <1> 	;movzx	ebx, al
  2219                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2220                              <1> 	; 12/01/2022 (BugFix)
  2221 00005FC1 C0E002              <1> 	shl	al, 2 ; * 4
  2222 00005FC4 8B88[AE6A0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2223                              <1> bread_0:
  2224 00005FCA 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2225                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2226                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2227 00005FCB 8B1D[BC740000]      <1> 	mov	ebx, [u.fofp]
  2228 00005FD1 8B03                <1> 	mov	eax, [ebx]
  2229 00005FD3 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2230                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2231                              <1> 			       ; / block #
  2232 00005FD6 39C8                <1> 	cmp	eax, ecx
  2233                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2234                              <1>        	                     ; / block number allowed
  2235                              <1> 	;jnb	error 	     ; 18/04/2013
  2236                              <1> 		; bhis error10 / yes, error
  2237                              <1> 	; 08/02/2022
  2238                              <1> 	;jb	short bread_1
  2239                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2240                              <1> 	;jmp	error
  2241 00005FD8 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2242                              <1> bread_1:
  2243                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2244                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2245                              <1> 	; eAX = Block number (zero based)
  2246                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2247                              <1> preread: ;; call preread
  2248 00005FDA BF[1B750000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2249 00005FDF E890020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2250                              <1> 	;; jc 	error
  2251                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2252                              <1>         ; eAX = Block/Sector number (r1)
  2253                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2254                              <1> 	; 14/03/2013
  2255 00005FE4 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2256                              <1>        		; br 1f / branch if block already in a I/O buffer
  2257 00005FE6 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2258                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2259 00005FEB E8DA010000          <1> 	call	poke
  2260                              <1>         	; jsr r0,poke / perform the read
  2261                              <1> 	;;jc	error ;2 0/07/2013
  2262                              <1> ; 1:
  2263                              <1>  		; clr *$ps / ps = 0
  2264                              <1>         	; rts r0
  2265                              <1> 	; 08/02/2022
  2266 00005FF0 7305                <1> 	jnc	short bread_2
  2267 00005FF2 E937010000          <1> 	jmp	dskrd_err
  2268                              <1> 	;
  2269                              <1> ;; return from preread
  2270                              <1> bread_2:
  2271 00005FF7 66810B0040          <1> 	or	word [ebx], 4000h 
  2272                              <1> 		; bis $40000,(r5) 
  2273                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2274                              <1> bread_3: ; 1:
  2275 00005FFC 66F7030024          <1> 	test	word [ebx], 2400h
  2276                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2277 00006001 7407                <1> 	jz	short bread_4
  2278                              <1> 		; beq 1f / no
  2279                              <1> 		; cmp cdev,$1 / disk or drum?
  2280                              <1> 		; ble 2f / yes
  2281                              <1> 		; tstb uquant / is the time quantum = 0?
  2282                              <1> 		; bne 2f / no, 2f
  2283                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2284                              <1> 		; jsr r0,sleep; 31. 
  2285                              <1> 			; / put process to sleep in channel 31 (tape)
  2286                              <1> 		; mov (sp)+,r5 / restore r5
  2287                              <1> 		; br 1b / go back
  2288                              <1> ; 2: / drum or disk
  2289                              <1>         ;; mov	cx, [s.wait_]+2 ;; 29/07/2013
  2290 00006003 E867EFFFFF          <1> 	call	idle
  2291                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2292 00006008 EBF2                <1> 	jmp	short bread_3
  2293                              <1>        		; br 1b
  2294                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2295 0000600A 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2296                              <1> 		; bic $40000,(r5) / clear bit 14
  2297                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2298 0000600F 83C308              <1> 	add	ebx, 8
  2299                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2300                              <1> 	; 09/06/2015
  2301 00006012 66833D[14750000]00  <1> 	cmp	word [u.pcount], 0
  2302 0000601A 7705                <1> 	ja	short bread_5
  2303 0000601C E814F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2304                              <1> bread_5:
  2305                              <1> 	; eBX = system (I/O) buffer address
  2306 00006021 E870000000          <1> 	call	dioreg
  2307                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2308                              <1> 	; esi = start address of the transfer (in the buffer)
  2309                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2310                              <1> 	; ecx = transfer count (in bytes)
  2311                              <1> 	;
  2312                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2313                              <1> ;   / of users data
  2314 00006026 F3A4                <1> 	rep	movsb
  2315                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2316                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2317                              <1>        		; bne 1b
  2318 00006028 59                  <1> 	pop	ecx ; **
  2319 00006029 833D[D0740000]00    <1> 	cmp	dword [u.count], 0
  2320                              <1> 		; tst u.count / done
  2321 00006030 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2322                              <1>        		; beq 1f / yes, return
  2323                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2324                              <1>        		; br bread / read some more
  2325                              <1> ; 1:
  2326 00006032 58                  <1> 	pop	eax ; ****
  2327                              <1>        		; mov (sp)+,r0
  2328 00006033 C3                  <1>         retn		; 09/06/2015
  2329                              <1> 	;jmp	ret_ 
  2330                              <1> 		;jmp ret / jump to routine that called readi
  2331                              <1> 
  2332                              <1> 	; 08/02/2022
  2333                              <1> brw_oov_err:
  2334 00006034 C705[1C750000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2334 0000603C 0000                <1>
  2335 0000603E E98BDAFFFF          <1> 	jmp	error
  2336                              <1> 
  2337                              <1> 	; 08/02/2022
  2338                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2339                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2340                              <1> 	; 26/04/2013
  2341                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2342                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2343                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2344                              <1> 
  2345                              <1> 	; 08/02/2022
  2346                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)				
  2347                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2348                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2349                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2350                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2351                              <1> 
  2352                              <1> bwrite: 
  2353                              <1> 	; 08/02/2022
  2354                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2355                              <1> 	; 14/07/2015
  2356                              <1> 	; 10/07/2015
  2357                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2358                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2359                              <1> 	;	
  2360                              <1> 	;; / write on block structured device
  2361                              <1> 	;
  2362                              <1> 	; INPUTS ->
  2363                              <1> 	;    [u.fopf] points to the block number
  2364                              <1> 	;    CX = maximum block number allowed on device
  2365                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2366                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2367                              <1> 	;    [u.count]	number of bytes to user desires to write
  2368                              <1> 	; OUTPUTS ->
  2369                              <1> 	;    [u.fopf] points to next consecutive block to be written into
  2370                              <1> 	;
  2371                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2372                              <1> 	;
  2373                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2374                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2375                              <1> 	;	is increased by 1. For example: If user/program request 
  2376                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2377                              <1> 	;  	the next block number just as 512 byte writing is done.
  2378                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2379                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2380                              <1> 	;       enough to keep byte position/offset of the disk), this
  2381                              <1> 	;	defect will not be corrected, user/program must request
  2382                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2383                              <1> 	;       for achieving correct result. In future version(s), 
  2384                              <1> 	;	this defect will be corrected by using different 
  2385                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2386                              <1> 
  2387                              <1>        		; jsr r0,tstdeve / test the device for an error
  2388                              <1> 	;push	ecx ; **
  2389                              <1> 	;26/04/2013
  2390                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2391 00006043 2C03                <1> 	sub	al, 3
  2392                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2393 00006045 A2[1B750000]        <1> 	mov	[u.brwdev], al
  2394                              <1> 	; 09/06/2015
  2395                              <1> 	;movzx	ebx, al
  2396                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2397                              <1> 	; 12/01/2022 (BugFix)
  2398 0000604A C0E002              <1> 	shl	al, 2 ; * 4
  2399 0000604D 8B88[AE6A0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2400                              <1> bwrite_0:
  2401 00006053 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2402                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2403                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2404 00006054 8B1D[BC740000]      <1> 	mov	ebx, [u.fofp]
  2405 0000605A 8B03                <1> 	mov	eax, [ebx]       
  2406 0000605C C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2407                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2408 0000605F 39C8                <1> 	cmp	eax, ecx
  2409                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2410                              <1>        	                     ; / block number allowed
  2411                              <1> 	;jnb	error	     ; 18/04/2013
  2412                              <1> 		; bhis error10 / yes, error
  2413                              <1>      	; 08/02/2022
  2414                              <1> 	;jb	short bwrite_1
  2415                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2416                              <1> 	;jmp	error
  2417 00006061 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2418                              <1> bwrite_1:
  2419                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2420                              <1> 		; inc *u.fofp / no, increment block number
  2421                              <1> 	; 09/06/2015 - 10/07/2015
  2422 00006063 66833D[14750000]00  <1> 	cmp	word [u.pcount], 0
  2423 0000606B 7705                <1> 	ja	short bwrite_2
  2424 0000606D E8BFF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2425                              <1> bwrite_2:
  2426 00006072 BF[1B750000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2427 00006077 E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2428                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2429                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2430 0000607C E815000000          <1>         call	dioreg
  2431                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2432                              <1> 	; esi = destination address (in the buffer)
  2433                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2434                              <1> 	; ecx = transfer count (in bytes)
  2435                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2436 00006081 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2437 00006083 F3A4                <1> 	rep	movsb
  2438                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2439                              <1>        		; dec r3 / area to the I/O buffer
  2440                              <1>        		; bne 1b
  2441 00006085 E80D010000          <1> 	call	dskwr
  2442                              <1> 		; jsr r0,dskwr / write it out on the device
  2443 0000608A 59                  <1> 	pop	ecx ; **
  2444 0000608B 833D[D0740000]00    <1>         cmp     dword [u.count], 0
  2445                              <1> 		; tst u.count / done
  2446 00006092 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2447                              <1> 		; beq 1f / yes, 1f
  2448                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2449                              <1>        		; br bwrite / go back and write next block
  2450                              <1> ; 1:
  2451 00006094 58                  <1> 	pop	eax ; ****
  2452                              <1>        		; mov (sp)+,r0
  2453 00006095 C3                  <1> 	retn		; 09/06/2015
  2454                              <1>         ;jmp	ret_ 
  2455                              <1> 		; jmp ret / return to routine that called writei
  2456                              <1> ;error10:
  2457                              <1> ;       jmp     error  ; / see 'error' routine
  2458                              <1> 
  2459                              <1> dioreg:
  2460                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2461                              <1> 	; 14/07/2015
  2462                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2463                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2464                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2465                              <1> 	;	
  2466                              <1> 	; bookkeeping on block transfers of data
  2467                              <1> 	;
  2468                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2469                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2470                              <1> 	; 10/07/2015
  2471                              <1> 	; * returns byte offset from beginning of current sector buffer
  2472                              <1> 	; (beginning of data) in ESI
  2473                              <1> 	;
  2474 00006096 8B0D[D0740000]      <1> 	mov	ecx, [u.count]
  2475                              <1> 		; mov u.count,r3 / move char count to r3
  2476                              <1> 	; 08/02/2022
  2477 0000609C 31D2                <1> 	xor	edx, edx
  2478 0000609E B602                <1> 	mov	dh, 2
  2479                              <1> 	; edx = 512
  2480 000060A0 39D1                <1> 	cmp	ecx, edx ; 512
  2481                              <1> 	;cmp 	ecx, 512
  2482                              <1> 		; cmp r3,$512. / more than 512. char?
  2483 000060A2 7602                <1> 	jna	short dioreg_0
  2484                              <1> 		; blos 1f / no, branch
  2485 000060A4 89D1                <1> 	mov	ecx, edx ; 512
  2486                              <1> 	;mov	ecx, 512
  2487                              <1> 		; mov $512.,r3 / yes, just take 512.
  2488                              <1> dioreg_0:
  2489                              <1> 	; 09/06/2015
  2490 000060A6 663B0D[14750000]    <1> 	cmp	cx, [u.pcount]
  2491 000060AD 7607                <1> 	jna	short dioreg_1
  2492 000060AF 668B0D[14750000]    <1> 	mov	cx, [u.pcount]
  2493                              <1> dioreg_1:
  2494                              <1> ; 1:
  2495 000060B6 8B15[CC740000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2496                              <1> 	        ; mov u.base,r2 / put users base in r2
  2497 000060BC 010D[D4740000]      <1> 	add	[u.nread], ecx
  2498                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2499 000060C2 290D[D0740000]      <1> 	sub	[u.count], ecx
  2500                              <1> 		; sub r3,u.count / update count
  2501 000060C8 010D[CC740000]      <1> 	add	[u.base], ecx
  2502                              <1> 		; add r3,u.base / update base
  2503                              <1> 	; 10/07/2015
  2504                              <1> 	; Retro UNIX 386 v1 - modification !
  2505                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2506                              <1> 	; (It will point to next byte position instead of next block no.)
  2507 000060CE 8B35[BC740000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2508 000060D4 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2509 000060D6 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2510 000060D8 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2511 000060DD 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2512 000060DF 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2513                              <1> 	; 09/06/2015 - 10/07/2015
  2514 000060E1 66290D[14750000]    <1> 	sub	[u.pcount], cx
  2515 000060E8 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2516 000060EE 8B3D[10750000]      <1> 	mov	edi, [u.pbase]
  2517 000060F4 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2518 000060FA 01D7                <1> 	add	edi, edx
  2519 000060FC 893D[10750000]      <1> 	mov	[u.pbase], edi
  2520 00006102 010D[10750000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2521 00006108 C3                  <1> 	retn
  2522                              <1> 		; rts r0 / return
  2523                              <1> 
  2524                              <1> dskrd:
  2525                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2526                              <1> 	; 18/08/2015
  2527                              <1> 	; 02/07/2015
  2528                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2529                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2530                              <1> 	;
  2531                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2532                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2533                              <1> 	; (number specified in r1) in the acquired buffer.)
  2534                              <1> 	; If the device is busy at the time dskrd is called,	
  2535                              <1> 	; dskrd calls idle.
  2536                              <1> 	; 
  2537                              <1> 	; INPUTS ->
  2538                              <1> 	;    r1 - block number
  2539                              <1> 	;    cdev - current device number 
  2540                              <1> 	; OUTPUTS ->
  2541                              <1> 	;    r5 - points to first data word in I/O buffer
  2542                              <1> 	;
  2543                              <1> 	; ((AX = R1)) input/output
  2544                              <1> 	; ((BX = R5)) output 
  2545                              <1> 	;
  2546                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2547                              <1> 	;
  2548 00006109 E859010000          <1> 	call 	bufaloc
  2549                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2550                              <1> 			       ; / get a free I/O buffer
  2551                              <1> 	;;jc	error ; 20/07/2013
  2552 0000610E 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2553                              <1>        		; br 1f / branch if block already in a I/O buffer
  2554                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2555 00006110 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2556                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2557                              <1> 		               ; / I/O queue entry for buffer
  2558 00006115 E8B0000000          <1> 	call	poke
  2559                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2560                              <1> 			    ; /	bit 10=1 says read
  2561                              <1> 	; 09/06/2015
  2562                              <1> 	;jnc	short dskrd_1
  2563                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2564                              <1> 	;jmp	error
  2565                              <1> 	; 08/02/2022
  2566 0000611A 7212                <1> 	jc	short dskrd_3
  2567                              <1> dskrd_1: ; 1:
  2568                              <1>        		; clr *$ps
  2569 0000611C 66F7030024          <1>        	test	word [ebx], 2400h
  2570                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2571                              <1> 				; / jump to idle
  2572 00006121 7407                <1>        	jz	short dskrd_2
  2573                              <1> 		; beq 1f
  2574                              <1>         ;;mov   ecx, [s.wait_]
  2575 00006123 E847EEFFFF          <1>        	call	idle
  2576                              <1> 		; jsr r0,idle; s.wait+2
  2577 00006128 EBF2                <1> 	jmp 	short dskrd_1
  2578                              <1>        		; br 1b
  2579                              <1> dskrd_2: ; 1:
  2580 0000612A 83C308              <1>         add	ebx, 8
  2581                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2582                              <1> 			  ; / just read in
  2583 0000612D C3                  <1>        	retn
  2584                              <1> 		; rts r0
  2585                              <1> dskrd_err: 
  2586                              <1> 	; 08/02/2022
  2587                              <1> 	; (jump from 'bread' error)	
  2588                              <1> dskrd_3:	
  2589                              <1> 	; 08/02/2022
  2590 0000612E 803D[1B750000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2591 00006135 7509                <1> 	jne	short dskrd_4 ; no
  2592                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2593 00006137 C605[1B750000]00    <1> 	mov	byte [u.brwdev], 0
  2594 0000613E EB0A                <1> 	jmp	short dskrd_5
  2595                              <1> dskrd_4:
  2596 00006140 C705[1C750000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2596 00006148 0000                <1>
  2597                              <1> dskrd_5:
  2598 0000614A E97FD9FFFF          <1> 	jmp	error
  2599                              <1> 
  2600                              <1> bwslot:
  2601                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2602                              <1> 	; 10/07/2015
  2603                              <1> 	;	If the block/sector is not placed in a buffer
  2604                              <1> 	;	before 'wslot', it must be read before
  2605                              <1> 	;	it is written! (Otherwise transfer counts less
  2606                              <1> 	;	than 512 bytes will be able to destroy existing 
  2607                              <1> 	;	data on disk.)
  2608                              <1> 	;
  2609                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2610                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2611                              <1> 	; Retro UNIX 8086 v1 modification !
  2612                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2613                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2614                              <1> 	;	-> eAX = block number
  2615                              <1> 	;
  2616 0000614F E820010000          <1> 	call	bufaloc_0
  2617 00006154 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2618                              <1> 	; 12/01/2022
  2619                              <1> 	; ebx = buffer header address
  2620                              <1> bwslot_0:
  2621                              <1> 	; 10/07/2015
  2622 00006156 8B35[BC740000]      <1> 	mov	esi, [u.fofp]
  2623 0000615C 8B06                <1> 	mov	eax, [esi]
  2624 0000615E 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2625 00006163 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2626                              <1> 		       ; recent disk data must be placed in the buffer
  2627 00006165 813D[D0740000]0002- <1> 	cmp	dword [u.count], 512
  2627 0000616D 0000                <1>
  2628 0000616F 730F                <1> 	jnb	short wslot_0	
  2629                              <1> bwslot_1:
  2630 00006171 E89AFFFFFF          <1> 	call	dskrd_0
  2631                              <1> 	; 12/01/2022
  2632                              <1> 	; ebx = buffer data address = buffer header addr + 8
  2633 00006176 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again	
  2634 00006179 EB05                <1> 	jmp 	short wslot_0
  2635                              <1> 
  2636                              <1> wslot:
  2637                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2638                              <1> 	; 		(32 bit modifications)
  2639                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2640                              <1> 	;
  2641                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2642                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2643                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2644                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2645                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2646                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2647                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2648                              <1> 	;
  2649                              <1> 	; INPUTS ->
  2650                              <1>  	;    r1 - block number
  2651                              <1> 	;    cdev - current (block/disk) device number
  2652                              <1>  	;
  2653                              <1> 	; OUTPUTS ->
  2654                              <1> 	;    bufp - bits 9 and 15 are set, 
  2655                              <1> 	;           the remainder of the word left unchanged
  2656                              <1> 	;    r5 - points to first data word in I/O buffer
  2657                              <1> 	;
  2658                              <1> 	; ((AX = R1)) input/output
  2659                              <1> 	; ((BX = R5)) output 
  2660                              <1> 	;
  2661                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2662                              <1> 
  2663 0000617B E8E7000000          <1> 	call	bufaloc
  2664                              <1> 	; 10/07/2015
  2665                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2666                              <1>         	; br 1f / word in buffer in r5
  2667                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2668                              <1>         ; eAX = Block/Sector number (r1)
  2669                              <1> wslot_0: ;1:
  2670 00006180 66F7030024          <1>      	test	word [ebx], 2400h
  2671                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2672                              <1> 				; / of I/O queue entry
  2673 00006185 7407                <1> 	jz	short wslot_1
  2674                              <1>                 ; beq 1f / branch if 10, 13 zero (i.e., not reading, 
  2675                              <1> 		       ; / or not waiting to read)
  2676                              <1> 
  2677                              <1>         ;;mov	ecx, [s.wait_] ; 29/07/2013
  2678 00006187 E8E3EDFFFF          <1> 	call	idle
  2679                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2680                              <1>        	                     ; / idle
  2681 0000618C EBF2                <1> 	jmp	short wslot_0
  2682                              <1> 		; br 1b / till finished
  2683                              <1> wslot_1: ;1:
  2684 0000618E 66810B0082          <1>         or      word [ebx], 8200h
  2685                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2686                              <1>                             	 ; / (write, inhibit bits)
  2687                              <1>        		; clr *$ps / clear processor status
  2688 00006193 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2689                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2690                              <1> 			  ; / for this block
  2691                              <1> dskwr_1:	; 08/02/2022
  2692 00006196 C3                  <1>        	retn
  2693                              <1> 		; rts r0
  2694                              <1> dskwr:
  2695                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.2)
  2696                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2697                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2698                              <1> 	;
  2699                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2700                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2701                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2702                              <1> 	; previously has supplied all the information required in the
  2703                              <1> 	; I/O queue entry.
  2704                              <1> 	;
  2705                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2706                              <1> 	;
  2707 00006197 8B1D[64740000]      <1> 	mov	ebx, [bufp]
  2708 0000619D 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2709                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2710                              <1>                                   ; / bottom of queue
  2711 000061A2 E823000000          <1> 	call	poke
  2712                              <1> 	; 09/06/2015
  2713 000061A7 73ED                <1> 	jnc	short dskwr_1
  2714                              <1> 	; 08/02/2022
  2715 000061A9 803D[1B750000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2716 000061B0 7509                <1> 	jne	short dskwr_0 ; no
  2717                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2718 000061B2 C605[1B750000]00    <1> 	mov	byte [u.brwdev], 0
  2719 000061B9 EB0A                <1> 	jmp	short dskwr_2
  2720                              <1> dskwr_0:
  2721 000061BB C705[1C750000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2721 000061C3 0000                <1>
  2722                              <1> dskwr_2:
  2723 000061C5 E904D9FFFF          <1> 	jmp	error
  2724                              <1> ;dskwr_1:
  2725                              <1> ;	retn
  2726                              <1> 
  2727                              <1> ;ppoke:
  2728                              <1>        		; mov $340,*$ps
  2729                              <1>        		; jsr r0,poke
  2730                              <1>        		; clr *$ps
  2731                              <1> 		; rts r0
  2732                              <1> poke:
  2733                              <1> 	; 29/11/2021 (32 bit reg push-pop)
  2734                              <1> 	; 24/10/2015
  2735                              <1> 	; 20/08/2015
  2736                              <1> 	; 18/08/2015
  2737                              <1> 	; 02/07/2015
  2738                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2739                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2740                              <1> 	;
  2741                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2742                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2743                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2744                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2745                              <1> 	;
  2746                              <1> 	; Basic I/O functions for all block structured devices
  2747                              <1> 	;
  2748                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2749                              <1> 	;
  2750                              <1> 	; 20/07/2013 modifications
  2751                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2752                              <1> 	; INPUTS -> 
  2753                              <1> 	;        (EBX = buffer header address)
  2754                              <1> 	; OUTPUTS ->
  2755                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2756                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2757                              <1> 	;		(drive not ready or r/w error!)
  2758                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2759                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2760                              <1> 	;        (also it indicates invalid buffer data)
  2761                              <1> 	;
  2762 000061CA 53                  <1> 	push	ebx
  2763                              <1>        		; mov r1,-(sp)
  2764                              <1>        		; mov r2,-(sp)
  2765                              <1>        		; mov r3,-(sp)
  2766 000061CB 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2767                              <1> 	;
  2768                              <1> 	; 09/06/2015
  2769                              <1> 	; (permit read/write after a disk R/W error)
  2770 000061CC 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2771 000061CE B001                <1> 	mov	al, 1
  2772 000061D0 D2E0                <1> 	shl	al, cl
  2773 000061D2 8405[8C740000]      <1> 	test 	al, [active] ; busy ? (error)
  2774 000061D8 7408                <1> 	jz	short poke_0
  2775 000061DA F6D0                <1> 	not	al
  2776 000061DC 2005[8C740000]      <1> 	and	[active], al ; reset busy bit for this device only
  2777                              <1> poke_0:
  2778 000061E2 BE[84740000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2779                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2780                              <1> 					 ; / I/O queue pointer
  2781                              <1> poke_1: ; 1:
  2782 000061E7 83EE04              <1>         sub	esi, 4
  2783 000061EA 8B1E                <1> 	mov	ebx, [esi]
  2784                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2785 000061EC 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2786 000061EF F6C406              <1>        	test	ah, 06h
  2787                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2788                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2789                              <1> 			       ; / queue entry
  2790 000061F2 745C                <1>         jz      short poke_5
  2791                              <1> 		; beq 2f / branch to 2f if both are clear
  2792                              <1> 	; 31/07/2013
  2793                              <1> 	;test	ah, 0B0h ; (*)
  2794                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2795                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2796                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2797                              <1> 		; bne 2f / branch if any are set
  2798                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2799                              <1>     		; movb (r1),r3 / get device id
  2800 000061F4 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2801                              <1> 	;mov	edi, ecx ; 26/04/2013
  2802 000061F7 31C0                <1> 	xor 	eax, eax ; 0
  2803                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2804                              <1> 		; tstb deverr(r3) / test for errors on this device
  2805                              <1>        	;jna	short poke_2 
  2806                              <1> 		; beq 3f / branch if no errors
  2807                              <1> 	; 02/07/2015
  2808                              <1> 	;dec	eax
  2809                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2810                              <1>        		; mov $-1,2(r1) / destroy associativity
  2811                              <1> 	;shr	eax, 24
  2812                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2813                              <1> 		; clrb 1(r1) / do not do I/O
  2814                              <1> 	;jmp	short poke_5
  2815                              <1>         ;       ; br 2f
  2816                              <1>                 ; rts r0
  2817                              <1> poke_2: ; 3:
  2818                              <1> 	; 02/07/2015
  2819 000061F9 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2820 000061FB 7453                <1> 	jz	short poke_5
  2821 000061FD FEC0                <1> 	inc	al ; mov ax, 1
  2822 000061FF FEC9                <1> 	dec	cl
  2823 00006201 7402                <1> 	jz	short poke_3
  2824                              <1> 	; 26/04/2013 Modification
  2825                              <1> 	;inc	al ; mov ax, 1
  2826                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2827                              <1> 	;jz	short poke_3 ; cl = 0
  2828 00006203 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2829                              <1> poke_3:
  2830                              <1> 	;test	[active], ax
  2831 00006205 8405[8C740000]      <1> 	test	[active], al
  2832                              <1> 		; bit $2,active / test disk busy bit
  2833 0000620B 7543                <1> 	jnz     short poke_5
  2834                              <1> 		; bne 2f / branch if bit is set
  2835                              <1> 	;or	[active], ax
  2836 0000620D 0805[8C740000]      <1> 	or	[active], al
  2837                              <1> 		; bis $2,active / set disk busy bit
  2838 00006213 50                  <1> 	push	eax ; 29/11/2021
  2839 00006214 E8D1000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2840                              <1> 	;mov    [edi+drv.error], ah
  2841 00006219 58                  <1> 	pop	eax
  2842 0000621A 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2843                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2844                              <1> 	;jna	short poke_4
  2845                              <1> 		; tstb deverr(r3) / test for errors on this device
  2846                              <1>        		; beq 3f / branch if no errors
  2847                              <1> 	; 02/07/2015 (32 bit modification)
  2848                              <1> 	; 20/07/2013
  2849 0000621C C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2850                              <1>        		; mov $-1,2(r1) / destroy associativity
  2851 00006223 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2852                              <1> 		; clrb 1(r1) / do not do I/O
  2853 00006228 EB26                <1> 	jmp     short poke_5
  2854                              <1> poke_4:	; 20/07/2013
  2855                              <1> 	; 17/07/2013
  2856 0000622A F6D0                <1> 	not 	al 
  2857 0000622C 2005[8C740000]      <1> 	and	[active], al ; reset, not busy
  2858                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2859                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2860 00006232 668B03              <1> 	mov	ax, [ebx]
  2861                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2862 00006235 66250006            <1>         and	ax, 600h
  2863                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2864 00006239 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2865                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2866 0000623E C0E403              <1> 	shl	ah, 3
  2867                              <1>        		; rol r3
  2868                              <1>                 ; rol r3
  2869                              <1>                 ; rol r3	
  2870 00006241 660903              <1> 	or	[ebx], ax
  2871                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2872                              <1> 			   ; bits 12 and 13
  2873 00006244 E826EDFFFF          <1> 	call	idle ; 18/01/2014
  2874                              <1> 	;; sti
  2875                              <1> 	;hlt 	; wait for a hardware interrupt
  2876                              <1> 	;; cli
  2877                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2878                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2879                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2880                              <1> 	; method, this procedure will wait for a time according to
  2881                              <1> 	; multi tasking and time sharing concept.
  2882                              <1> 	;
  2883                              <1> 	; 24/10/2015
  2884                              <1> 	;not	ax 
  2885 00006249 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2886 0000624D 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2887                              <1> poke_5: ;2:
  2888 00006250 81FE[64740000]      <1>         cmp     esi, bufp
  2889                              <1> 		; cmp r2,$bufp / test to see if entire I/O queue 
  2890                              <1>                             ; / has been scanned
  2891 00006256 778F                <1> 	ja      short poke_1
  2892                              <1> 		; bhi 1b
  2893                              <1> 	; 24/03/2013
  2894                              <1>        		; mov (sp)+,r3
  2895                              <1>        		; mov (sp)+,r2
  2896                              <1>        		; mov (sp)+,r1
  2897 00006258 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2898 00006259 5B                  <1> 	pop 	ebx
  2899                              <1> 	; 02/07/2015 (32 bit modification)
  2900                              <1> 	; 20/07/2013
  2901                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2902 0000625A 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2903                              <1> 	;	
  2904                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2905                              <1> 	; or written successfully; even if an error occurs while
  2906                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2907                              <1> 	;
  2908                              <1> 	; 09/06/2015
  2909 0000625D F5                  <1> 	cmc
  2910 0000625E C3                  <1> 	retn
  2911                              <1>                 ; rts r0
  2912                              <1> 
  2913                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatibility code
  2914                              <1> get_system_time:
  2915                              <1> 	; 27/10/2021
  2916                              <1> 	; 21/02/2020 - Retro UNIX 386 v2
  2917                              <1> 	; get system time
  2918                              <1> 	;  (from recent value which is saved in RTC interrupt)
  2919                              <1> 	; Input:
  2920                              <1> 	; 	none
  2921                              <1> 	; Return:
  2922                              <1> 	;   	eax = system time in unix epoch format 
  2923                              <1> 	;
  2924                              <1> 	; Modified registers: eax, ecx, edx
  2925                              <1> 	
  2926                              <1> 	; 27/11/2021
  2927 0000625F 53                  <1> 	push	ebx
  2928 00006260 E8A0D3FFFF          <1> 	call	epoch
  2929 00006265 5B                  <1> 	pop	ebx
  2930 00006266 C3                  <1> 	retn
  2931                              <1> 	
  2932                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2)
  2933                              <1> 	;  ('get_serial_number' is not used in v1.2 kernel)
  2934                              <1> ;get_serial_number:
  2935                              <1> 	; temporary - 21/02/2020
  2936                              <1> 	; 26/04/2020 (esi)
  2937                              <1> 	; 25/04/2020
  2938                              <1> 	; (Possible) Modified registers: eax, ecx, edx
  2939                              <1> 	; (edi, ebx & esi registers must be preserved)
  2940                              <1> 	; Return:
  2941                              <1> 	; eax = 32 bit serial number  
  2942                              <1> 	; (edx = high 32 bit of 64 bit serial number)
  2943                              <1> 	; -64 bit serial numbers will not be used in RUNIX 386 v2-
  2944                              <1> 	
  2945                              <1> 	;retn
  2946                              <1> 
  2947                              <1> bufaloc:
  2948                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2949                              <1> 	; 20/08/2015
  2950                              <1> 	; 19/08/2015
  2951                              <1> 	; 02/07/2015
  2952                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2953                              <1> 	;	     (32 bit modifications)	
  2954                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2955                              <1> 	;
  2956                              <1> 	; bufaloc - Block device I/O buffer allocation
  2957                              <1> 	; 
  2958                              <1> 	; INPUTS ->
  2959                              <1> 	;    r1 - block number
  2960                              <1> 	;    cdev - current (block/disk) device number
  2961                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2962                              <1> 	; OUTPUTS ->
  2963                              <1> 	;    r5 - pointer to buffer allocated
  2964                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2965                              <1> 	;
  2966                              <1> 	; ((AX = R1)) input/output
  2967                              <1> 	; ((BX = R5)) output
  2968                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2969                              <1> 	;    zf=1 -> block already in a I/O buffer
  2970                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2971                              <1> 	;    ((DL = Device ID))
  2972                              <1> 	;    (((DH = 0 or 1)))
  2973                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2974                              <1> 	;    ((CX and DH will not be used after return)))
  2975                              <1> 
  2976                              <1> 	;;push 	esi ; ***
  2977                              <1> 		; mov r2,-(sp) / save r2 on stack
  2978                              <1>        		; mov $340,*$ps / set processor priority to 7
  2979                              <1> 	; 20/07/2013
  2980                              <1> 	; 26/04/2013
  2981                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2982                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  2983                              <1> 	;add	edi, ebx
  2984                              <1> 	; 09/01/2022
  2985 00006267 0FB63D[89740000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2986 0000626E 81C7[8A740000]      <1> 	add	edi, rdev
  2987                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2988                              <1> 			;; eDI points to device id.
  2989 00006274 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2990                              <1> 	; 11/06/2021
  2991 00006277 80BB[CA6A0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2992 0000627E 720F                <1> 	jb	short bufaloc_9
  2993 00006280 C705[1C750000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2993 00006288 0000                <1>
  2994 0000628A E93FD8FFFF          <1> 	jmp	error
  2995                              <1> bufaloc_9:
  2996 0000628F 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2997                              <1> bufaloc_10: ; 02/07/2015
  2998 00006291 31ED                <1> 	xor 	ebp, ebp ; 0
  2999 00006293 55                  <1> 	push	ebp ; 0
  3000 00006294 89E5                <1>         mov     ebp, esp	
  3001                              <1> 	;
  3002                              <1> bufaloc_1: ;1:
  3003                              <1> 		; clr -(sp) / vacant buffer
  3004 00006296 BE[64740000]        <1>         mov 	esi, bufp
  3005                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3006                              <1> 			     ; / entrys in buffer area
  3007                              <1> bufaloc_2: ;2:
  3008 0000629B 8B1E                <1> 	mov	ebx, [esi]
  3009                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3010                              <1> 			    ; queue entry into r5
  3011 0000629D 66F70300F6          <1> 	test	word [ebx], 0F600h
  3012                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3013 000062A2 7503                <1>         jnz	short bufaloc_3
  3014                              <1> 		; bne 3f / branch when 
  3015                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3016                              <1>                        ; / (i.e., buffer busy)
  3017 000062A4 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  3018                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  3019                              <1> 			; / found points to word 2 of I/O queue entry)
  3020                              <1> bufaloc_3: ;3:
  3021                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3022                              <1> 	;
  3023 000062A7 3813                <1> 	cmp	[ebx], dl	
  3024                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3025                              <1> 			       ; / as current device
  3026 000062A9 7508                <1> 	jne	short bufaloc_4
  3027                              <1>        		; bne 3f
  3028 000062AB 394304              <1> 	cmp	[ebx+4], eax
  3029                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3030                              <1> 			     ; / same as current block number
  3031 000062AE 7503                <1>        	jne	short bufaloc_4
  3032                              <1> 		; bne 3f
  3033                              <1> 	;add	esp, 4
  3034 000062B0 59                  <1> 	pop	ecx
  3035                              <1>        		; tst (sp)+ / bump stack pointer
  3036 000062B1 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3037                              <1> 				; jump to bufaloc_6 in original Unix v1
  3038                              <1>        		; br 1f / use this buffer
  3039                              <1> bufaloc_4: ;3:
  3040 000062B3 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3041                              <1> 	;
  3042 000062B6 81FE[7C740000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3043                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3044 000062BC 72DD                <1> 	jb	short bufaloc_2
  3045                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3046                              <1>                        ; / buffers not checked)
  3047 000062BE 5E                  <1>         pop	esi
  3048                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3049                              <1> 			     ; / to last free block
  3050 000062BF 09F6                <1>        	or	esi, esi 
  3051 000062C1 7507                <1> 	jnz	short bufaloc_5
  3052                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3053                              <1> 	        ; / if a free buffer is found branch to 2f
  3054                              <1>         ;; mov  ecx, [s.wait_]
  3055 000062C3 E8A7ECFFFF          <1> 	call	idle
  3056                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  3057 000062C8 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3058                              <1>        		; br 1b
  3059                              <1> bufaloc_5: ;2:
  3060                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3061 000062CA FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3062                              <1> bufaloc_6: ;1:
  3063 000062CC 8B1E                <1>         mov    	ebx, [esi] 
  3064                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3065                              <1> 			     ; / entry in r5
  3066                              <1> 	;; 26/04/2013
  3067                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3068 000062CE 8813                <1> 	mov 	[ebx], dl
  3069                              <1> 		; movb cdev,(r5) / put current device number 
  3070                              <1> 				 ; / in I/O queue entry
  3071 000062D0 894304              <1> 	mov 	[ebx+4], eax
  3072                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3073                              <1> 			     ; / of I/O queue entry
  3074                              <1> bufaloc_7: ;1:
  3075 000062D3 81FE[64740000]      <1>         cmp	esi, bufp
  3076                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3077                              <1> 			     ; / and put latest assigned
  3078 000062D9 760A                <1> 	jna	short bufaloc_8	
  3079                              <1>        		; blos 1f / buffer on the top 
  3080                              <1> 			; / (this makes if the lowest priority)
  3081 000062DB 83EE04              <1> 	sub	esi, 4
  3082 000062DE 8B0E                <1> 	mov	ecx, [esi]
  3083 000062E0 894E04              <1> 	mov	[esi+4], ecx
  3084                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3085 000062E3 EBEE                <1> 	jmp 	short bufaloc_7        
  3086                              <1> 		; br 1b
  3087                              <1> bufaloc_8: ;1:
  3088 000062E5 891E                <1>         mov	[esi], ebx
  3089                              <1> 		; mov r5,(r2)
  3090                              <1> 	;;pop	esi ; ***
  3091                              <1>        		; mov (sp)+,r2 / restore r2
  3092 000062E7 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3093                              <1> 		; Retro UNIX 8086 v1 modification
  3094                              <1> 		; zf=1 --> block already is in an I/O buffer
  3095                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3096 000062E9 C3                  <1> 	retn
  3097                              <1> 		; rts r0
  3098                              <1> 
  3099                              <1> diskio:
  3100                              <1> 	; 12/02/2022
  3101                              <1> 	; 10/02/2022
  3102                              <1> 	; 08/02/2022
  3103                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3104                              <1> 	; 28/11/2021
  3105                              <1> 	; 10/07/2015
  3106                              <1> 	; 02/07/2015
  3107                              <1> 	; 16/06/2015
  3108                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3109                              <1> 	;	     (80386 protected mode modifications)	
  3110                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3111                              <1> 	;
  3112                              <1> 	; Retro UNIX 8086 v1 feature only !
  3113                              <1> 	;
  3114                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3115                              <1> 	; 04/07/2009 - 20/07/2011
  3116                              <1> 	;
  3117                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3118                              <1> 	;
  3119                              <1>         ; INPUTS ->
  3120                              <1> 	; 	   ebx = System I/O Buffer header address
  3121                              <1> 	;
  3122                              <1>         ; OUTPUTS -> cf=0 --> done 
  3123                              <1> 	; 	     cf=1 --> error code in AH
  3124                              <1> 	;	     ; 08/02/2022
  3125                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3126                              <1> 	;		error code in [u.error]
  3127                              <1> 	;		
  3128                              <1> 	; (Modified registers: eax, ecx, edx)
  3129                              <1> 	
  3130                              <1> ;rw_disk_sector:
  3131                              <1> 	; 12/02/2022
  3132                              <1> 	; 10/02/2022
  3133                              <1> 	; 08/02/2022
  3134                              <1> 	; 28/11/2021
  3135                              <1> 	; 10/07/2015
  3136                              <1> 	; 02/07/2015
  3137                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3138                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3139                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3140                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3141                              <1> 	;
  3142                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3143 000062EA B602                <1> 	mov	dh, 2
  3144                              <1> 	;mov	ax, [ebx]
  3145                              <1> 	; 28/11/2021
  3146 000062EC 8B03                <1> 	mov	eax, [ebx]
  3147                              <1> 	;
  3148 000062EE 56                  <1> 	push	esi ; ****
  3149 000062EF 53                  <1> 	push	ebx ; ***
  3150                              <1> 	;
  3151 000062F0 0FB6C8              <1> 	movzx	ecx, al
  3152                              <1> 	; 28/11/2021
  3153                              <1> 	;mov	ecx, eax
  3154 000062F3 89CE                <1> 	mov	esi, ecx
  3155                              <1> 	;
  3156 000062F5 38F1                <1> 	cmp	cl, dh ; 2
  3157 000062F7 7202                <1> 	jb	short rwdsk0
  3158 000062F9 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3159                              <1> rwdsk0:
  3160 000062FB A2[7B6A0000]        <1> 	mov	[drv], al
  3161 00006300 81C6[CA6A0000]      <1> 	add	esi, drv.status
  3162                              <1> 	; 11/06/2015
  3163 00006306 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3164 00006309 7204                <1> 	jb      short rwdsk1
  3165                              <1> 	; 'drive not ready' error
  3166                              <1> 	; 10/02/2022
  3167                              <1> 	; 08/02/2022
  3168                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3169                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3170                              <1> 	;;jmp	error
  3171                              <1> 	;stc	; cf = 1
  3172                              <1> 	;retn
  3173                              <1> 	; 10/02/2022
  3174 0000630B B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3175 0000630D EB20                <1> 	jmp	short rwdsk_err1
  3176                              <1> rwdsk1:
  3177 0000630F F6C402              <1> 	test	ah, 2
  3178                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3179                              <1> 			 ; write bit
  3180 00006312 7402                <1> 	jz	short rwdsk2
  3181                              <1> 	;test	ah, 4
  3182                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3183                              <1> 	;		 ; read bit
  3184                              <1> 	;jz	short diskio_ret
  3185 00006314 FEC6                <1> 	inc	dh ; 03h = write
  3186                              <1> rwdsk2:
  3187 00006316 88C2                <1> 	mov	dl, al
  3188 00006318 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3189 0000631B 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3190 0000631D C0E102              <1> 	shl	cl, 2
  3191 00006320 81C1[AE6A0000]      <1> 	add	ecx, drv.size ; disk size
  3192 00006326 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3193 00006328 7214                <1> 	jb      short rwdsk3
  3194                              <1>  	; 'out of volume' error
  3195                              <1> 	; 10/02/2022
  3196                              <1> 	; 08/02/2022
  3197                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3198                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3199                              <1> 	;;jmp	error
  3200                              <1> 	;stc	; cf = 1
  3201                              <1> 	;retn
  3202                              <1> 	; 10/02/2022
  3203 0000632A B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3204                              <1> rwdsk_err1:
  3205 0000632F C605[1B750000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3206 00006336 890D[1C750000]      <1> 	mov	[u.error], ecx ; 12/02/2022
  3207 0000633C EB30                <1> 	jmp	short rwdsk_err2
  3208                              <1> rwdsk3:
  3209                              <1> 	; 11/06/2015
  3210 0000633E 83C304              <1> 	add	ebx, 4 ; buffer address
  3211 00006341 C605[3F750000]04    <1> 	mov	byte [retry_count], 4
  3212 00006348 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3213 0000634B 7432                <1>         jz      short rwdsk_chs
  3214                              <1> rwdsk_lba:
  3215                              <1> 	; LBA read/write (with private LBA function) 
  3216                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3217 0000634D 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3218 00006350 89C1                <1> 	mov	ecx, eax ; sector number
  3219                              <1> 	; ebx = buffer (data) address
  3220                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3221                              <1> rwdsk_lba_retry:
  3222                              <1> 	;mov	dl, [drv]
  3223                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3224 00006352 B419                <1> 	mov	ah, 1Ch - 03h ; LBA write function number - 3
  3225 00006354 00F4                <1> 	add	ah, dh		
  3226 00006356 B001                <1> 	mov	al, 1
  3227                              <1> 	;int	13h
  3228 00006358 E82FC2FFFF          <1> 	call	int13h
  3229 0000635D 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3230 0000635F 730E                <1> 	jnc	short rwdsk_lba_ok
  3231 00006361 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3232 00006364 7408                <1>         je      short rwdsk_lba_fails
  3233 00006366 FE0D[3F750000]      <1> 	dec	byte [retry_count]
  3234 0000636C 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3235                              <1> rwdsk_err2:	; 10/02/2022
  3236                              <1> rwdsk_lba_fails:
  3237 0000636E F9                  <1> 	stc
  3238                              <1> rwdsk_lba_ok:
  3239 0000636F 5B                  <1> 	pop	ebx ; ***
  3240 00006370 5E                  <1> 	pop	esi ; ****
  3241 00006371 C3                  <1> 	retn
  3242                              <1> rwdsk_lba_reset:
  3243 00006372 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3244                              <1> 	;int	13h
  3245 00006374 E813C2FFFF          <1>         call	int13h
  3246 00006379 73D7                <1> 	jnc     short rwdsk_lba_retry
  3247 0000637B 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3248 0000637D EBF0                <1> 	jmp	short rwdsk_lba_ok
  3249                              <1> 	;
  3250                              <1> 	; CHS read (convert LBA address to CHS values)	
  3251                              <1> rwdsk_chs:
  3252                              <1> 	; 10/07/2015
  3253 0000637F 81EE[CA6A0000]      <1> 	sub	esi, drv.status
  3254 00006385 89F1                <1> 	mov	ecx, esi
  3255 00006387 81C6[D16A0000]      <1> 	add 	esi, drv.error
  3256                              <1> 	; 02/07/2015
  3257                              <1> 	; 16/06/2015
  3258                              <1>  	; 11/06/2015 
  3259 0000638D 53                  <1> 	push	ebx ; ** ; buffer
  3260 0000638E D1E1                <1> 	shl	ecx, 1
  3261 00006390 51                  <1> 	push	ecx ; * 
  3262                              <1> 	;
  3263 00006391 89CB                <1> 	mov	ebx, ecx
  3264 00006393 8835[3D750000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3265 00006399 31D2                <1> 	xor	edx, edx ; 0
  3266                              <1> 	; 09/01/2022
  3267                              <1> 	;sub	ecx, ecx 
  3268 0000639B 81C3[A06A0000]      <1>         add     ebx, drv.spt
  3269 000063A1 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3270                              <1> 		; EDX:EAX = LBA
  3271 000063A4 F7F1                <1> 	div	ecx
  3272 000063A6 88D1                <1> 	mov	cl, dl	; sector number - 1
  3273 000063A8 FEC1                <1> 	inc	cl	; sector number (1 based)
  3274 000063AA 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3275                              <1> 	;push	cx
  3276 000063AB 51                  <1> 	push	ecx ; 28/11/2021
  3277 000063AC 81C3[926A0000]      <1>         add     ebx, drv.heads
  3278 000063B2 668B0B              <1> 	mov	cx, [ebx] ; heads
  3279 000063B5 31D2                <1> 	xor	edx, edx
  3280                              <1> 		; EAX = cylinders * heads + head
  3281 000063B7 F7F1                <1> 	div	ecx
  3282                              <1> 	;pop	cx     ; sector number
  3283 000063B9 59                  <1> 	pop	ecx ; 28/11/2021
  3284 000063BA 88D6                <1> 	mov	dh, dl ; head number
  3285 000063BC 8A15[7B6A0000]      <1> 	mov	dl, [drv]
  3286 000063C2 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3287 000063C4 C0E406              <1> 	shl	ah, 6
  3288 000063C7 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3289                              <1> 		       ; sector (bits 0-7)
  3290 000063C9 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3291                              <1> 		; CL = sector (bits 0-5)
  3292                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3293                              <1> 		; CH = cylinder (bits 0-7)
  3294                              <1> 		; DH = head
  3295                              <1> 		; DL = drive
  3296                              <1> 	;
  3297 000063CA C605[3F750000]04    <1> 	mov	byte [retry_count], 4
  3298                              <1> rwdsk_retry:	
  3299 000063D1 8A25[3D750000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3300 000063D7 B001                <1> 	mov	al, 1 ; sector count	
  3301                              <1> 	;int	13h
  3302 000063D9 E8AEC1FFFF          <1> 	call	int13h
  3303 000063DE 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3304 000063E0 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3305 000063E2 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3306 000063E5 7408                <1> 	je	short rwdsk_fails
  3307 000063E7 FE0D[3F750000]      <1> 	dec	byte [retry_count]
  3308 000063ED 7504                <1> 	jnz	short rwdsk_reset
  3309                              <1> rwdsk_fails:
  3310 000063EF F9                  <1> 	stc
  3311                              <1> rwdsk_ok:
  3312 000063F0 5B                  <1> 	pop	ebx ; ***
  3313 000063F1 5E                  <1> 	pop	esi ; ****
  3314 000063F2 C3                  <1> 	retn
  3315                              <1> rwdsk_reset:
  3316                              <1> 	; 02/02/2015
  3317 000063F3 28E4                <1> 	sub	ah, ah
  3318 000063F5 80FA80              <1> 	cmp	dl, 80h
  3319 000063F8 7202                <1> 	jb	short rwdsk_fd_reset
  3320 000063FA B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3321                              <1> rwdsk_fd_reset:
  3322                              <1> 	;int	13h
  3323 000063FC E88BC1FFFF          <1>         call	int13h
  3324 00006401 73CE                <1> 	jnc	short rwdsk_retry
  3325 00006403 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3326 00006405 EBE9                <1> 	jmp 	short rwdsk_ok
  3327                              <1> 
  3328                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3329                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3330                              <1> ;
  3331                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3332                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3333                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3334                              <1> ; that uses hardware -transfer has been completed- interrupt inside it. 
  3335                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3336                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3337                              <1> ; as in original unix v1.
  3338                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3339                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3340                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3341                              <1> ;
  3342                              <1> ; Erdogan tan (10/07/2015) 
  3343                              <1> 
  3344                              <1> ;drum: / interrupt handler
  3345                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3346                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3347                              <1> ;                                      / error
  3348                              <1> ;               br 3f / no, error
  3349                              <1> ;       br      2f / error
  3350                              <1> ;
  3351                              <1> ;disk:
  3352                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3353                              <1> ;       jmp     *$0f
  3354                              <1> ;0:
  3355                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3356                              <1> ;      	        br 3f / no, errors
  3357                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3358                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3359                              <1> ;                        / to 1f
  3360                              <1> ;       br      4f
  3361                              <1> ;1:
  3362                              <1> ;       bit     $20000,rkcs
  3363                              <1> ;       beq     4f / wait for seek complete
  3364                              <1> ;       mov     $0b,0b-2
  3365                              <1> ;       mov     rkap,r1
  3366                              <1> ;2:
  3367                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3368                              <1> ;                          / the disk buffer
  3369                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3370                              <1> ;       inc     r1
  3371                              <1> ;       asr     (r1)
  3372                              <1> ;       asr     (r1)
  3373                              <1> ;       asr     (r1) / reissue request
  3374                              <1> ;       dec     r1
  3375                              <1> ;3:
  3376                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3377                              <1> ;       mov     ac,-(sp)
  3378                              <1> ;       mov     mq,-(sp) / put these on the stack
  3379                              <1> ;       mov     sc,-(sp)
  3380                              <1> ;       jsr     r0,poke
  3381                              <1> ;       mov     (sp)+,sc
  3382                              <1> ;       mov     (sp)+,mq / pop them off stack
  3383                              <1> ;       mov     (sp)+,ac
  3384                              <1> ;4:
  3385                              <1> ;       jmp     retisp / u4-3
  3386                              <1> ;
  3387                              <1> ;trapt:                  / r2 points to the
  3388                              <1> ;       mov     (r0)+,r2 / device control register
  3389                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3390                              <1> ;       tst     (sp)+
  3391                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3392                              <1> ;       bge     4b / device still active so branch
  3393                              <1> ;       bit     (r0),active / was device busy?
  3394                              <1> ;       beq     4b / no, stray interrupt
  3395                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3396                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3397                              <1> ;       bge     2f / if no error jump to 2f
  3398                              <1> ;       tst     (r0)+ / skip on error
  3399                              <1> ; 2:
  3400                              <1> ;       jmp     (r0)
  2080                                  %include 'u9.s'      ; 29/06/2015
  2081                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2082                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2083                              <1> ; ****************************************************************************
  2084                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS9.INC
  2085                              <1> ; Last Modification: 16/02/2022
  2086                              <1> ; ----------------------------------------------------------------------------
  2087                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2088                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2089                              <1> ;
  2090                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2091                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2092                              <1> ; <Bell Laboratories (17/3/1972)>
  2093                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2094                              <1> ;
  2095                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2096                              <1> ;
  2097                              <1> ; ****************************************************************************
  2098                              <1> 
  2099                              <1> getch:
  2100                              <1> 	; 30/06/2015
  2101                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2102 00006407 28C0                <1> 	sub	al, al ; 0
  2103                              <1> getch_q: ; 06/08/2015
  2104 00006409 8A25[B66F0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2105 0000640F EB06                <1>         jmp     short getc_n
  2106                              <1> 
  2107                              <1> getc: 
  2108                              <1> 	; 12/11/2015
  2109                              <1> 	; 15/09/2015
  2110                              <1> 	; 01/07/2015
  2111                              <1> 	; 30/06/2015
  2112                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2113                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2114                              <1> 	;
  2115                              <1> 	; Retro UNIX 8086 v1 modification !
  2116                              <1> 	; 
  2117                              <1> 	; 'getc' gets (next) character 
  2118                              <1> 	;	 from requested TTY (keyboard) buffer 
  2119                              <1> 	; INPUTS ->
  2120                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2121                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2122                              <1> 	;	(Keyboard buffer will point to 
  2123                              <1> 	;			next character at next call)
  2124                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2125                              <1> 	;	(Keyboard buffer will point to 
  2126                              <1> 	;			current character at next call)
  2127                              <1> 	; OUTPUTS ->
  2128                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2129                              <1> 	;     			 ZF=0 -> AX has (current) character
  2130                              <1> 	;      AL = ascii code
  2131                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2132                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2133                              <1> 	; Original UNIX V1 'getc': 
  2134                              <1> 	;		get a character off character list
  2135                              <1> 	;
  2136                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2137                              <1> 	;
  2138                              <1> 	; 30/06/2015 (32 bit modifications)
  2139                              <1> 	; 16/07/2013
  2140                              <1> 	; mov 	[getctty], ah
  2141                              <1> 	;
  2142                              <1> 
  2143 00006411 8A25[DD740000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2144                              <1> getc_n:
  2145                              <1> 	; 30/06/2015
  2146 00006417 08E4                <1> 	or	ah, ah
  2147 00006419 740D                <1> 	jz	short getc0 
  2148 0000641B D0E4                <1> 	shl	ah, 1
  2149 0000641D 0FB6DC              <1> 	movzx	ebx, ah
  2150 00006420 81C3[B86F0000]      <1> 	add	ebx, ttychr
  2151 00006426 EB05                <1> 	jmp	short getc1
  2152                              <1> getc0:
  2153 00006428 BB[B86F0000]        <1> 	mov	ebx, ttychr
  2154                              <1> getc1:
  2155 0000642D 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2156                              <1> 				; (by kb_int)	
  2157 00006430 6609C9              <1> 	or	cx, cx
  2158 00006433 7507                <1> 	jnz	short getc2
  2159 00006435 20C0                <1> 	and 	al, al
  2160 00006437 7415                <1> 	jz	short getc_s
  2161                              <1> 	;xor	ax, ax
  2162                              <1> 	; 30/11/2021
  2163 00006439 31C0                <1> 	xor	eax, eax
  2164 0000643B C3                  <1> 	retn
  2165                              <1> getc2:	
  2166 0000643C 20C0                <1> 	and	al, al
  2167 0000643E 6689C8              <1> 	mov	ax, cx
  2168 00006441 66B90000            <1> 	mov	cx, 0
  2169 00006445 7506                <1> 	jnz	short getc3
  2170                              <1> getc_sn:
  2171 00006447 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2172 0000644A 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2173                              <1> getc3:
  2174 0000644D C3                  <1> 	retn
  2175                              <1> getc_s:
  2176                              <1> 	; 12/11/2015
  2177                              <1> 	; 15/09/2015
  2178                              <1> 	; 01/07/2015
  2179                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2180                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2181                              <1> 	;
  2182                              <1> 	; tty  of the current process is not 
  2183                              <1> 	; current tty (ptty); so, current process only 
  2184                              <1> 	; can use keyboard input when its tty becomes 
  2185                              <1> 	; current tty (ptty).
  2186                              <1> 	; 'sleep' is for preventing an endless lock
  2187                              <1> 	; during this tty input request.
  2188                              <1> 	; (Because, the user is not looking at the video page
  2189                              <1> 	; of the process to undersand there is a keyboard
  2190                              <1> 	; input request.)
  2191                              <1> 	;
  2192                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2193                              <1> 	;
  2194                              <1> 	; 05/10/2013
  2195                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2196                              <1> 	;
  2197                              <1> 	; 10/10/2013
  2198                              <1> gcw0:
  2199 0000644E B10A                <1> 	mov	cl, 10 ; ch = 0
  2200                              <1> gcw1:	
  2201                              <1> 	; 12/11/2015
  2202 00006450 E886D7FFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2203                              <1> 	; 10/10/2013
  2204 00006455 E815EBFFFF          <1> 	call	idle
  2205 0000645A 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2206                              <1> 				; (by kb_int)
  2207 0000645D 6609C0              <1> 	or	ax, ax
  2208                              <1> ;	jnz	short gcw3
  2209 00006460 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2210                              <1> 	; 30/06/2015
  2211 00006462 FEC9                <1> 	dec	cl
  2212 00006464 75EA                <1> 	jnz	short gcw1
  2213                              <1> 	;
  2214 00006466 8A25[DD740000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2215                              <1> ;	; 10/12/2013
  2216                              <1> ;	cmp 	ah, [ptty]
  2217                              <1> ;	jne	short gcw2
  2218                              <1> ;	; 14/02/2014
  2219                              <1> ;	cmp	byte [u.uno], 1
  2220                              <1> ;	jna	short gcw0		
  2221                              <1> ;gcw2:
  2222 0000646C E891EBFFFF          <1> 	call	sleep
  2223                              <1> 	;
  2224                              <1> 	; 20/09/2013
  2225 00006471 8A25[DD740000]      <1> 	mov	ah, [u.ttyn]
  2226 00006477 30C0                <1> 	xor 	al, al
  2227 00006479 EB9C                <1> 	jmp	short getc_n
  2228                              <1> ;gcw3:
  2229                              <1> gcw2: 	; 15/09/2015
  2230                              <1> 	; 10/10/2013
  2231 0000647B 30C9                <1> 	xor	cl, cl
  2232 0000647D EBC8                <1> 	jmp	short getc_sn
  2233                              <1> 
  2234                              <1> putc:	
  2235                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2236                              <1> 	; 13/08/2015
  2237                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2238                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2239                              <1> 	;
  2240                              <1> 	; Retro UNIX 8086 v1 modification !
  2241                              <1> 	; 
  2242                              <1> 	; 'putc' puts a character 
  2243                              <1> 	;	 onto requested (tty) video page or
  2244                              <1> 	;	 serial port
  2245                              <1> 	; INPUTS ->
  2246                              <1> 	;     AL = ascii code of the character
  2247                              <1> 	;     AH = video page (tty) number (0 to 7)
  2248                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2249                              <1> 	; OUTPUTS ->
  2250                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2251                              <1> 	;      			ZF=0 -> AX has (current) character
  2252                              <1> 	;     cf=0 and AH = 0 -> no error
  2253                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)
  2254                              <1> 	; 
  2255                              <1> 	; Original UNIX V1 'putc': 
  2256                              <1> 	;     put a character at the end of character list
  2257                              <1> 	;
  2258                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2259                              <1> 	;
  2260 0000647F 80FC07              <1> 	cmp	ah, 7
  2261 00006482 770A                <1>         ja      short sndc ; 05/12/2021
  2262                              <1> 	; 30/06/2015
  2263 00006484 0FB6DC              <1> 	movzx	ebx, ah
  2264                              <1> 	; 13/08/2015
  2265 00006487 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2266 00006489 E92CAFFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2267                              <1> 
  2268                              <1> sndc:   ; <Send character>
  2269                              <1> 	;
  2270                              <1> 	; 12/01/2022
  2271                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2272                              <1> 	; 17/11/2015
  2273                              <1> 	; 16/11/2015
  2274                              <1> 	; 11/11/2015
  2275                              <1> 	; 10/11/2015
  2276                              <1> 	; 09/11/2015
  2277                              <1> 	; 08/11/2015
  2278                              <1> 	; 07/11/2015
  2279                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2280                              <1> 	; 29/10/2015
  2281                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2282                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2283                              <1> 	;
  2284                              <1> 	; Retro UNIX 8086 v1 feature only !
  2285                              <1> 	;
  2286                              <1> 	; ah = [u.ttyn]
  2287                              <1> 	;
  2288                              <1> 	; 30/06/2015
  2289 0000648E 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2290                              <1> 	; 07/11/2015
  2291 00006491 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2292                              <1> sndc0:
  2293                              <1> 	; 07/11/2015
  2294 00006494 E8BFEBFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2295 00006499 7405                <1> 	jz	short sndc1
  2296 0000649B E83BD7FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2297                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2298                              <1> sndc1:
  2299                              <1> 	; 16/11/2015
  2300                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2301                              <1> 	; 24/12/2021
  2302 000064A0 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2303                              <1> sndcx:
  2304 000064A2 8A83[FA6F0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2305 000064A8 8AA3[F86F0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2306                              <1> 	;
  2307                              <1> 	; 17/11/2015
  2308                              <1> 	; check 'request for response' status
  2309 000064AE 80BB[F46F0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2310 000064B5 740A                <1> 	jz	short query
  2311                              <1> response:
  2312 000064B7 FE05[F76F0000]      <1> 	inc 	byte [comqr] ; query or response status
  2313 000064BD B0FF                <1> 	mov	al, 0FFh	 
  2314 000064BF EB14                <1> 	jmp	short sndc3
  2315                              <1> query:
  2316 000064C1 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2317 000064C3 750E                <1> 	jnz 	short sndc2 ; normal character
  2318                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2319                              <1> 	;je	short sndc2  ; yes, already responded
  2320                              <1> 	; 16/11/2015
  2321                              <1> 	; query: request for response (again)
  2322 000064C5 8883[F86F0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2323 000064CB FE05[F76F0000]      <1> 	inc 	byte [comqr] ; query or response status
  2324 000064D1 EB02                <1> 	jmp	short sndc3
  2325                              <1> sndc2:
  2326 000064D3 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2327                              <1> sndc3:
  2328 000064D5 8883[FA6F0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2329 000064DB 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2330                              <1> 	; 30/06/2015
  2331 000064DD E888D0FFFF          <1> 	call	sp_status ; get serial port status
  2332                              <1> 	; AL = Line status, AH = Modem status
  2333                              <1> 	; 07/11/2015
  2334 000064E2 A880                <1> 	test	al, 80h
  2335 000064E4 7504                <1> 	jnz	short sndc4
  2336 000064E6 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2337 000064E8 751A                <1> 	jnz	short sndc5
  2338                              <1> sndc4: 	; Check line status again
  2339                              <1> 	; 16/11/2015
  2340                              <1> 	;push	cx
  2341                              <1> 	; 24/12/2021
  2342 000064EA 51                  <1> 	push	ecx
  2343                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2344                              <1> 	; 12/01/2022
  2345 000064EB 31C9                <1> 	xor	ecx, ecx
  2346 000064ED B106                <1> 	mov	cl, 6
  2347 000064EF E8BDAFFFFF          <1> 	call	WAITF
  2348                              <1> 	;pop	cx
  2349                              <1> 	; 24/12/1021
  2350 000064F4 59                  <1> 	pop	ecx
  2351                              <1> 	;
  2352 000064F5 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2353 000064F7 E86ED0FFFF          <1> 	call	sp_status ; get serial port status
  2354                              <1> 	; 16/11/2015
  2355                              <1> 	; 09/11/2015
  2356                              <1> 	; 08/11/2015
  2357 000064FC A880                <1> 	test	al, 80h	; time out error
  2358 000064FE 7565                <1>         jnz     short sndc7
  2359 00006500 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2360 00006502 7461                <1>         jz	short sndc7
  2361                              <1> sndc5:  
  2362 00006504 8A83[FA6F0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2363 0000650A 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2364 0000650E 28DE                <1> 	sub	dh, bl
  2365 00006510 EE                  <1> 	out	dx, al	   ; send on serial port
  2366                              <1> 	; 10/11/2015
  2367                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2368                              <1> 	; (to improve text flow to the terminal)
  2369                              <1> 	; ('diskette.inc': 'WAITF')
  2370                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2371                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2372                              <1> 	;push	cx
  2373                              <1> 	; 24/12/2021
  2374 00006511 51                  <1> 	push	ecx
  2375                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2376                              <1> 	; 12/01/2022
  2377 00006512 29C9                <1> 	sub	ecx, ecx
  2378 00006514 B106                <1> 	mov	cl, 6
  2379 00006516 E896AFFFFF          <1> 	call	WAITF
  2380                              <1> 	;pop	cx
  2381                              <1> 	; 24/12/1021
  2382 0000651B 59                  <1> 	pop	ecx
  2383                              <1>     	;
  2384                              <1> 	; 07/11/2015
  2385 0000651C 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2386                              <1> 	;
  2387 0000651E E847D0FFFF          <1> 	call	sp_status ; get serial port status
  2388                              <1> 	; AL = Line status, AH = Modem status
  2389                              <1> 	;
  2390 00006523 E830EBFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2391 00006528 7405                <1> 	jz	short sndc6
  2392 0000652A E8ACD6FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2393                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2394                              <1> sndc6:
  2395 0000652F 3C80                <1> 	cmp	al, 80h
  2396 00006531 7332                <1> 	jnb	short sndc7		
  2397                              <1> 	;
  2398 00006533 803D[F76F0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2399 0000653A 7244                <1> 	jb	short sndc8 	; no, normal character
  2400 0000653C 883D[F76F0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2401                              <1> 	; 17/11/2015
  2402 00006542 E828EAFFFF          <1> 	call	idle
  2403                              <1> 	;
  2404 00006547 38BB[FA6F0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2405                              <1>         ;ja	sndc2       ; response (will be followed by
  2406                              <1> 			    ; a normal character)
  2407                              <1> 	; 24/12/2021
  2408 0000654D 7602                <1> 	jna	short sndc_10
  2409 0000654F EB82                <1> 	jmp	sndc2
  2410                              <1> sndc_10:
  2411                              <1> 	; Query request must be responded by the terminal
  2412                              <1> 	; before sending a normal character !
  2413 00006551 53                  <1> 	push	ebx
  2414                              <1> 	;push	cx ; *** cl = character (to be sent)
  2415                              <1> 	; 24/12/2021
  2416 00006552 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2417 00006553 8A25[DD740000]      <1> 	mov	ah, [u.ttyn]
  2418 00006559 E8A4EAFFFF          <1> 	call	sleep ; this process will be awakened by
  2419                              <1> 		      ; received data available interrupt
  2420                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2421                              <1> 	; 24/12/2021
  2422 0000655E 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2423 0000655F 5B                  <1> 	pop	ebx
  2424 00006560 E93DFFFFFF          <1>         jmp	sndcx
  2425                              <1> sndc7:
  2426                              <1> 	 ; 16/11/2015
  2427 00006565 803D[F76F0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2428 0000656C 7213                <1> 	jb	short sndc9 	; no
  2429                              <1> 	;
  2430 0000656E 88BB[F86F0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2431 00006574 88BB[FA6F0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2432                              <1> 	;
  2433 0000657A 883D[F76F0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2434                              <1> sndc8:
  2435 00006580 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2436                              <1> sndc9:
  2437                              <1> 	; AL = Line status, AH = Modem status
  2438 00006581 C3                  <1> 	retn
  2439                              <1> 
  2440                              <1> get_cpos:
  2441                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2442                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2443                              <1> 	;
  2444                              <1> 	; INPUT -> bl = video page number
  2445                              <1> 	; RETURN -> dx = cursor position
  2446                              <1> 
  2447 00006582 53                  <1> 	push	ebx
  2448 00006583 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2449 00006586 D0E3                <1> 	shl	bl, 1
  2450 00006588 81C3[A66F0000]      <1> 	add	ebx, cursor_posn
  2451 0000658E 668B13              <1> 	mov	dx, [ebx]
  2452 00006591 5B                  <1> 	pop	ebx
  2453 00006592 C3                  <1> 	retn
  2454                              <1> 
  2455                              <1> read_ac_current:
  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 -> ax = character (al) and attribute (ah)
  2461                              <1> 
  2462 00006593 E888AFFFFF          <1> 	call 	find_position ; 'video.inc'
  2463                              <1> 	; dx = status port
  2464                              <1> 	; esi = cursor location/address
  2465 00006598 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2466 0000659E 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2467 000065A1 C3                  <1> 	retn
  2468                              <1> 
  2469                              <1> syssleep:
  2470                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2471                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2472                              <1> 	;
  2473                              <1> 	; Retro UNIX 8086 v1 feature only
  2474                              <1> 	; (INPUT -> none)
  2475                              <1> 	;
  2476 000065A2 0FB61D[F9740000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2477 000065A9 8AA3[C3700000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2478 000065AF E84EEAFFFF          <1> 	call	sleep
  2479 000065B4 E935D5FFFF          <1> 	jmp	sysret
  2480                              <1> 
  2481                              <1> vp_clr:
  2482                              <1> 	; Reset/Clear Video Page
  2483                              <1> 	;
  2484                              <1> 	; 05/12/2021 - (Retro UNIX 386 v1.2)
  2485                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2486                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2487                              <1> 	;
  2488                              <1> 	; Retro UNIX 8086 v1 feature only !
  2489                              <1> 	;
  2490                              <1> 	; INPUTS -> 
  2491                              <1> 	;   BL = video page number	 
  2492                              <1> 	;
  2493                              <1> 	; OUTPUT ->
  2494                              <1> 	;   none
  2495                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2496                              <1> 	;
  2497                              <1> 	; 04/12/2013
  2498 000065B9 28C0                <1> 	sub	al, al
  2499                              <1> 	; al = 0 (clear video page)
  2500                              <1> 	; bl = video page
  2501 000065BB B407                <1> 	mov	ah, 07h
  2502                              <1> 	; ah = 7 (attribute/color)
  2503                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2504                              <1> 	; 05/12/2021
  2505 000065BD 31C9                <1> 	xor	ecx, ecx
  2506 000065BF 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2507 000065C3 E882AFFFFF          <1> 	call	scroll_up
  2508                              <1> 	; bl = video page
  2509                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2510                              <1> 	; 05/12/2021
  2511 000065C8 31D2                <1> 	xor	edx, edx
  2512 000065CA E9F5AEFFFF          <1> 	jmp 	set_cpos
  2513                              <1> 
  2514                              <1> sysmsg:
  2515                              <1> 	; 11/12/2021
  2516                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2517                              <1> 	; 11/11/2015
  2518                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2519                              <1> 	; Print user-application message on user's console tty
  2520                              <1> 	;
  2521                              <1> 	; Input -> EBX = Message address
  2522                              <1> 	;	   ECX = Message length (max. 255)
  2523                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2524                              <1> 	;
  2525 000065CF 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2526                              <1> 	;ja	sysret ; nothing to do with big message size
  2527 000065D5 7779                <1> 	ja	short sysmsg8 ; 11/12/2021
  2528 000065D7 08C9                <1> 	or	cl, cl
  2529                              <1> 	;jz	sysret
  2530 000065D9 7475                <1> 	jz	short sysmsg8 ; 11/12/2021
  2531 000065DB 20D2                <1> 	and	dl, dl
  2532 000065DD 7502                <1> 	jnz	short sysmsg0
  2533 000065DF B207                <1> 	mov	dl, 07h ; default color
  2534                              <1> 		; (black background, light gray character)
  2535                              <1> sysmsg0:
  2536 000065E1 891D[CC740000]      <1> 	mov	[u.base], ebx
  2537 000065E7 8815[B76F0000]      <1> 	mov	[ccolor], dl ; color attributes
  2538 000065ED 89E5                <1> 	mov	ebp, esp
  2539 000065EF 31DB                <1> 	xor	ebx, ebx ; 0
  2540 000065F1 891D[D4740000]      <1> 	mov	[u.nread], ebx ; 0
  2541                              <1> 	;
  2542 000065F7 381D[1A750000]      <1> 	cmp	[u.kcall], bl ; 0
  2543 000065FD 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2544                              <1> 	;
  2545 000065FF 890D[D0740000]      <1> 	mov	[u.count], ecx
  2546 00006605 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ ; 04/12/2021
  2547                              <1> 	; 04/12/2021
  2548                              <1> 	; (dword alignment for esp)
  2549 00006606 F6C103              <1> 	test	cl, 3
  2550 00006609 7404                <1> 	jz	short sysmsg_7
  2551 0000660B 80C903              <1> 	or	cl, 3
  2552 0000660E 41                  <1> 	inc	ecx
  2553                              <1> sysmsg_7:
  2554 0000660F 29CC                <1> 	sub	esp, ecx
  2555 00006611 89E7                <1> 	mov	edi, esp
  2556 00006613 89E6                <1> 	mov	esi, esp
  2557 00006615 66891D[14750000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2558                              <1> 	; 11/11/2015 
  2559 0000661C 8A25[DE740000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2560                              <1> 	; 0 = none
  2561 00006622 FECC                <1> 	dec	ah
  2562 00006624 790C                <1> 	jns	short sysmsg1 
  2563 00006626 8A1D[F9740000]      <1> 	mov	bl, [u.uno] ; process number	
  2564 0000662C 8AA3[C3700000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2565                              <1> sysmsg1:
  2566 00006632 8825[DD740000]      <1> 	mov	[u.ttyn], ah
  2567                              <1> sysmsg2:
  2568 00006638 E80CF5FFFF          <1> 	call	cpass
  2569 0000663D 7416                <1> 	jz	short sysmsg5
  2570 0000663F AA                  <1> 	stosb
  2571 00006640 20C0                <1> 	and	al, al
  2572 00006642 75F4                <1> 	jnz	short sysmsg2
  2573                              <1> sysmsg3:
  2574 00006644 80FC07              <1> 	cmp	ah, 7 ; tty number
  2575 00006647 7711                <1> 	ja	short sysmsg6 ; serial port
  2576 00006649 E83E000000          <1> 	call	print_cmsg
  2577                              <1> sysmsg4:
  2578 0000664E 89EC                <1> 	mov	esp, ebp
  2579                              <1> sysmsg8: ; 11/12/2021	
  2580 00006650 E999D4FFFF          <1> 	jmp	sysret
  2581                              <1> sysmsg5:
  2582 00006655 C60700              <1> 	mov	byte [edi], 0
  2583 00006658 EBEA                <1> 	jmp	short sysmsg3
  2584                              <1> sysmsg6:
  2585 0000665A 8A06                <1> 	mov	al, [esi]
  2586 0000665C E82DFEFFFF          <1> 	call	sndc
  2587 00006661 72EB                <1> 	jc	short sysmsg4
  2588 00006663 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2589 00006666 76E6                <1> 	jna	short sysmsg4
  2590 00006668 46                  <1> 	inc 	esi
  2591 00006669 8A25[DD740000]      <1> 	mov	ah, [u.ttyn]
  2592 0000666F EBE9                <1> 	jmp	short sysmsg6
  2593                              <1> 
  2594                              <1> sysmsgk: ; Temporary (01/07/2015)
  2595                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2596                              <1> 	; (ECX -character count- will not be considered)
  2597 00006671 8B35[CC740000]      <1> 	mov	esi, [u.base]
  2598 00006677 8A25[B66F0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2599 0000667D 8825[DD740000]      <1> 	mov	[u.ttyn], ah
  2600 00006683 C605[1A750000]00    <1> 	mov	byte [u.kcall], 0
  2601 0000668A EBB8                <1> 	jmp	short sysmsg3
  2602                              <1> 	
  2603                              <1> print_cmsg: 
  2604                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2605                              <1> 	;
  2606                              <1> 	; print message (on user's console tty) 
  2607                              <1> 	;	with requested color
  2608                              <1> 	;
  2609                              <1> 	; INPUTS:
  2610                              <1> 	;	esi = message address
  2611                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2612                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2613                              <1> 	;
  2614 0000668C AC                  <1> 	lodsb
  2615                              <1> pcmsg1:
  2616 0000668D 56                  <1> 	push 	esi
  2617 0000668E 0FB61D[DD740000]    <1>         movzx   ebx, byte [u.ttyn]
  2618 00006695 8A25[B76F0000]      <1> 	mov	ah, [ccolor]
  2619 0000669B E81AADFFFF          <1> 	call 	write_tty
  2620 000066A0 5E                  <1> 	pop	esi
  2621 000066A1 AC                  <1> 	lodsb
  2622 000066A2 20C0                <1> 	and 	al, al  ; 0
  2623 000066A4 75E7                <1> 	jnz 	short pcmsg1
  2624 000066A6 C3                  <1> 	retn
  2625                              <1> 
  2626                              <1> sysgeterr:
  2627                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.2
  2628                              <1> 	; 09/12/2015
  2629                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2630                              <1> 	; Get last error number or page fault count
  2631                              <1> 	; (for debugging)
  2632                              <1> 	;
  2633                              <1> 	; Input -> EBX = return type
  2634                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2635                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2636                              <1> 	;	   FFFFFFFEh = total page fault count
  2637                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2638                              <1> 	;
  2639                              <1> 	; Output -> EAX = last error number or page fault count
  2640                              <1> 	;	   (depending on EBX input)
  2641                              <1> 	; 	
  2642 000066A7 21DB                <1> 	and 	ebx, ebx
  2643 000066A9 750F                <1> 	jnz	short glerr_2
  2644                              <1> glerr_0:
  2645 000066AB A1[1C750000]        <1> 	mov	eax, [u.error]
  2646                              <1> glerr_1:
  2647 000066B0 A3[A8740000]        <1> 	mov	[u.r0], eax
  2648                              <1> 	;retn
  2649                              <1>  	; 16/01/2022 (BugFix)
  2650 000066B5 E934D4FFFF          <1> 	jmp	sysret
  2651                              <1> glerr_2:
  2652 000066BA 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2653 000066BB 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2654 000066BD 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2655 000066BE 75EB                <1> 	jnz	short glerr_0
  2656 000066C0 A1[40700000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2657 000066C5 EBE9                <1>         jmp     short glerr_1
  2658                              <1> glerr_3:
  2659 000066C7 A1[20750000]        <1> 	mov 	eax, [u.pfcount]
  2660 000066CC EBE2                <1> 	jmp	short glerr_1
  2081                                  
  2082                                  ; 07/03/2015
  2083                                  ; Temporary Code
  2084                                  display_disks:
  2085 000066CE 803D[7E6A0000]00        	cmp 	byte [fd0_type], 0
  2086 000066D5 7605                    	jna 	short ddsks1
  2087 000066D7 E87D000000              	call	pdskm
  2088                                  ddsks1:
  2089 000066DC 803D[7F6A0000]00        	cmp	byte [fd1_type], 0
  2090 000066E3 760C                    	jna	short ddsks2
  2091 000066E5 C605[6F6C0000]31        	mov	byte [dskx], '1'
  2092 000066EC E868000000              	call	pdskm
  2093                                  ddsks2:
  2094 000066F1 803D[806A0000]00        	cmp	byte [hd0_type], 0
  2095 000066F8 7654                    	jna	short ddsk6
  2096 000066FA 66C705[6D6C0000]68-     	mov	word [dsktype], 'hd'
  2096 00006702 64                 
  2097 00006703 C605[6F6C0000]30        	mov	byte [dskx], '0'
  2098 0000670A E84A000000              	call	pdskm
  2099                                  ddsks3:
  2100 0000670F 803D[816A0000]00        	cmp	byte [hd1_type], 0
  2101 00006716 7636                    	jna	short ddsk6
  2102 00006718 C605[6F6C0000]31        	mov	byte [dskx], '1'
  2103 0000671F E835000000              	call	pdskm
  2104                                  ddsks4:
  2105 00006724 803D[826A0000]00        	cmp	byte [hd2_type], 0
  2106 0000672B 7621                    	jna	short ddsk6
  2107 0000672D C605[6F6C0000]32        	mov	byte [dskx], '2'
  2108 00006734 E820000000              	call	pdskm
  2109                                  ddsks5:
  2110 00006739 803D[836A0000]00        	cmp	byte [hd3_type], 0
  2111 00006740 760C                    	jna	short ddsk6
  2112 00006742 C605[6F6C0000]33        	mov	byte [dskx], '3'
  2113 00006749 E80B000000              	call	pdskm
  2114                                  ddsk6:
  2115 0000674E BE[7E6C0000]            	mov	esi, nextline
  2116 00006753 E806000000              	call	pdskml
  2117                                  pdskm_ok:
  2118 00006758 C3                      	retn
  2119                                  pdskm:
  2120 00006759 BE[6B6C0000]            	mov	esi, dsk_ready_msg
  2121                                  pdskml:	
  2122 0000675E AC                      	lodsb
  2123 0000675F 08C0                    	or	al, al
  2124 00006761 74F5                    	jz	short pdskm_ok
  2125 00006763 56                      	push	esi
  2126 00006764 31DB                    	xor	ebx, ebx ; 0
  2127                                  			; Video page 0 (bl=0)
  2128 00006766 B407                    	mov	ah, 07h ; Black background, 
  2129                                  			; light gray forecolor
  2130 00006768 E84DACFFFF              	call	write_tty
  2131 0000676D 5E                      	pop	esi
  2132 0000676E EBEE                    	jmp	short pdskml
  2133                                  
  2134                                  align 16
  2135                                  
  2136                                  gdt:	; Global Descriptor Table
  2137                                  	; (30/07/2015, conforming cs)
  2138                                  	; (26/03/2015)
  2139                                  	; (24/03/2015, tss)
  2140                                  	; (19/03/2015)
  2141                                  	; (29/12/2013)
  2142                                  	;
  2143 00006770 0000000000000000        	dw 0, 0, 0, 0	; NULL descriptor
  2144                                  	; 18/08/2014
  2145                                  			; 08h kernel code segment, base = 00000000h		
  2146 00006778 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2147                                  			; 10h kernel data segment, base = 00000000h	
  2148 00006780 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2149                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2150 00006788 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2151                                  			; 23h user data segment, base address = 400000h ; CORE
  2152 00006790 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2153                                  			; Task State Segment
  2154 00006798 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2155                                  			       ;  no IO permission in ring 3)
  2156                                  gdt_tss0:
  2157 0000679A 0000                    	dw 0 ; TSS base address, bits 0-15 
  2158                                  gdt_tss1:
  2159 0000679C 00                      	db 0 ; TSS base address, bits 16-23 
  2160                                  	      		; 49h	
  2161 0000679D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2162 0000679E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2163                                  gdt_tss2:
  2164 0000679F 00                      	db 0 ; TSS base address, bits 24-31 
  2165                                  
  2166                                  gdt_end:
  2167                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2168                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2169                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2170                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2171                                  
  2172                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2173                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2174                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2175                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2176                                  		; W= Writeable, A= Accessed
  2177                                  	
  2178                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2179                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2180                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2181                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2182                                  
  2183                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2184                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2185                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2186                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2187                                  	
  2188                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2189                                  
  2190                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2191                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2192                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2193                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2194                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2195                                  		; AVL= Available to programmers	
  2196                                  
  2197                                  gdtd:
  2198 000067A0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2199 000067A2 [70670000]                      dd gdt			; Address of the GDT
  2200                                  
  2201                                  	; 20/08/2014
  2202                                  idtd:
  2203 000067A6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2204 000067A8 [206D0000]                      dd idt			; Address of the IDT
  2205                                  
  2206                                  align 4
  2207                                  	; 21/08/2014
  2208                                  ilist:
  2209                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2210                                  	;
  2211                                  	; Exception list
  2212                                  	; 25/08/2014	
  2213 000067AC [1F080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2214 000067B0 [26080000]              	dd	exc1	
  2215 000067B4 [2D080000]              	dd 	exc2	
  2216 000067B8 [34080000]              	dd	exc3	
  2217 000067BC [38080000]              	dd	exc4	
  2218 000067C0 [3C080000]              	dd	exc5	
  2219 000067C4 [40080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2220 000067C8 [44080000]              	dd	exc7	
  2221 000067CC [48080000]              	dd	exc8	
  2222 000067D0 [4C080000]              	dd	exc9	
  2223 000067D4 [50080000]              	dd 	exc10	
  2224 000067D8 [54080000]              	dd	exc11
  2225 000067DC [58080000]              	dd	exc12
  2226 000067E0 [5C080000]              	dd	exc13	; 0Dh, General Protection Fault
  2227 000067E4 [60080000]              	dd 	exc14	; 0Eh, Page Fault
  2228 000067E8 [64080000]              	dd	exc15
  2229 000067EC [68080000]              	dd	exc16
  2230 000067F0 [6C080000]              	dd	exc17
  2231 000067F4 [70080000]              	dd 	exc18
  2232 000067F8 [74080000]              	dd	exc19
  2233 000067FC [78080000]              	dd 	exc20
  2234 00006800 [7C080000]              	dd	exc21
  2235 00006804 [80080000]              	dd	exc22
  2236 00006808 [84080000]              	dd	exc23
  2237 0000680C [88080000]              	dd 	exc24
  2238 00006810 [8C080000]              	dd	exc25
  2239 00006814 [90080000]              	dd	exc26
  2240 00006818 [94080000]              	dd	exc27
  2241 0000681C [98080000]              	dd 	exc28
  2242 00006820 [9C080000]              	dd	exc29
  2243 00006824 [A0080000]              	dd 	exc30
  2244 00006828 [A4080000]              	dd	exc31
  2245                                  	; Interrupt list
  2246 0000682C [5E060000]              	dd	timer_int	; INT 20h
  2247                                  		;dd	irq0	
  2248 00006830 [560B0000]              	dd	keyb_int	; 27/08/2014
  2249                                  		;dd	irq1
  2250 00006834 [79070000]              	dd	irq2
  2251                                  		; COM2 int
  2252 00006838 [7D070000]              	dd	irq3
  2253                                  		; COM1 int
  2254 0000683C [88070000]              	dd	irq4
  2255 00006840 [93070000]              	dd	irq5
  2256                                  ;DISKETTE_INT: ;06/02/2015
  2257 00006844 [39250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2258                                  		;dd	irq6
  2259                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2260                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2261 00006848 [070B0000]              	dd	default_irq7	; 25/02/2015
  2262                                  		;dd	irq7
  2263                                  ; Real Time Clock Interrupt
  2264 0000684C [AD090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2265                                  		;dd	irq8	; INT 28h
  2266 00006850 [A3070000]              	dd	irq9
  2267 00006854 [A7070000]              	dd	irq10
  2268 00006858 [AB070000]              	dd	irq11
  2269 0000685C [AF070000]              	dd	irq12
  2270 00006860 [B3070000]              	dd	irq13
  2271                                  ;HDISK_INT1:  ;06/02/2015 	
  2272 00006864 [5F2D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2273                                  		;dd	irq14
  2274                                  ;HDISK_INT2:  ;06/02/2015
  2275 00006868 [822D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2276                                  		;dd	irq15	; INT 2Fh
  2277                                  		; 14/08/2015
  2278 0000686C [CA390000]              	dd	sysent		; INT 30h (system calls)
  2279                                  	
  2280                                  	;dd	ignore_int
  2281 00006870 00000000                	dd	0
  2282                                  
  2283                                  ;;;
  2284                                  ;;; 11/03/2015
  2285                                  %include 'kybdata.s'	; KEYBOARD (BIOS) DATA
  2286                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2287                              <1> ; Last Modification: 11/03/2015
  2288                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2289                              <1> ;
  2290                              <1> ; ///////// KEYBOARD DATA ///////////////
  2291                              <1> 
  2292                              <1> ; 05/12/2014
  2293                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2294                              <1> ; 03/06/86  KEYBOARD BIOS
  2295                              <1> 
  2296                              <1> ;---------------------------------------------------------------------------------
  2297                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2298                              <1> ;---------------------------------------------------------------------------------
  2299                              <1> 
  2300                              <1> ;-----	TABLES FOR ALT CASE ------------
  2301                              <1> ;-----	ALT-INPUT-TABLE 
  2302 00006874 524F50514B          <1> K30:	db	82,79,80,81,75
  2303 00006879 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2304                              <1> ;-----	SUPER-SHIFT-TABLE 
  2305 0000687E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2306 00006884 161718191E1F        <1> 	db	22,23,24,25,30,31
  2307 0000688A 202122232425        <1> 	db	32,33,34,35,36,37
  2308 00006890 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2309 00006896 3132                <1> 	db	49,50
  2310                              <1> 
  2311                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2312                              <1> ;-----	KEY_TABLE 
  2313 00006898 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2314 00006899 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2315 0000689E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2316                              <1> _K6L    equ     $-_K6
  2317                              <1> 
  2318                              <1> ;-----	MASK_TABLE
  2319 000068A0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2320 000068A1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2321 000068A6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2322                              <1> 
  2323                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2324 000068A8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2325 000068AE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2326 000068B4 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2327 000068BA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2328 000068C0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2329 000068C6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2330 000068CC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2331 000068D2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2332 000068D8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2333 000068DE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2334                              <1> 	;				;----- FUNCTIONS ------		
  2335 000068E2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2336 000068E8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2337 000068EE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2338 000068F4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2339 000068FA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2340                              <1> 
  2341                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2342 00006900 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2342 00006909 39302D3D0809        <1>
  2343 0000690F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2343 00006918 705B5D0DFF61736466- <1>
  2343 00006921 67686A6B6C3B27      <1>
  2344 00006928 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2344 00006931 6D2C2E2FFF2AFF20FF  <1>
  2345                              <1> ;-----	LC TABLE SCAN
  2346 0000693A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2347 0000693F 4041424344          <1> 	db	64,65,66,67,68
  2348 00006944 FFFF                <1> 	db	-1,-1			; NL, SL
  2349                              <1> 
  2350                              <1> ;-----	KEYPAD TABLE
  2351 00006946 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2352 0000694C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2353 00006953 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2354                              <1> 
  2355                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2356 00006958 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2356 00006961 28295F2B0800        <1>
  2357 00006967 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2357 00006970 507B7D0DFF41534446- <1>
  2357 00006979 47484A4B4C3A22      <1>
  2358 00006980 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2358 00006989 4D3C3E3FFF2AFF20FF  <1>
  2359                              <1> ;-----	UC TABLE SCAN
  2360 00006992 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2361 00006997 595A5B5C5D          <1> 	db	89,90,91,92,93
  2362 0000699C FFFF                <1> 	db	-1,-1			; NL, SL
  2363                              <1> 
  2364                              <1> ;-----	NUM STATE TABLE
  2365 0000699E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2365 000069A7 3233302E            <1>
  2366                              <1> 	;
  2367 000069AB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2368                              <1> 
  2369                              <1> Align	4
  2370                              <1> ;----------------------------------------
  2371                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2372                              <1> ;----------------------------------------
  2373 000069B0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2374 000069B1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2375                              <1> 				; (29h default setting for video mode 3)
  2376                              <1> 				; Mode Select register Bits
  2377                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2378                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2379                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2380                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2381                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2382                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2383                              <1> 				;   BIT 6, 7 - Not Used
  2384                              <1> 
  2385                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2386                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2387                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2388                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2389                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2390                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2391                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2392                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2393                              <1> ; Mode & 37h = Video signal OFF
  2394                              <1> 			
  2395                              <1> 
  2396                              <1> ; 26/08/2014
  2397                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2398                              <1> ; Derived from IBM "pc-at" 
  2399                              <1> ; rombios source code (06/10/1985)
  2400                              <1> ; 'dseg.inc'
  2401                              <1> 
  2402                              <1> ;---------------------------------------;
  2403                              <1> ;	SYSTEM DATA AREA		;
  2404                              <1> ;----------------------------------------
  2405 000069B2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2406                              <1> 
  2407                              <1> ;----------------------------------------
  2408                              <1> ;	KEYBOARD DATA AREAS		;
  2409                              <1> ;----------------------------------------
  2410                              <1> 
  2411 000069B3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2412 000069B4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2413 000069B5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2414 000069B6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2415 000069B7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2416 000069B8 [C8690000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2417 000069BC [E8690000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2418 000069C0 [C8690000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2419 000069C4 [C8690000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2420                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2421 000069C8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2422                              <1> 
  2423                              <1> ; /// End Of KEYBOARD DATA ///
  2286                                  %include 'vidata.s'	; VIDEO (BIOS) DATA
  2287                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2288                              <1> ; Last Modification: 11/03/2015
  2289                              <1> ;		    (Data section for 'VIDEO.INC')	
  2290                              <1> ;
  2291                              <1> ; ///////// VIDEO DATA ///////////////
  2292                              <1> 
  2293                              <1> video_params:
  2294                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2295                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2296                              <1> 	; VIDEO MODE 3
  2297 000069E8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2298 000069EF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2299 000069F4 00000000            <1> 	db	0,0,0,0
  2300                              <1> 
  2301                              <1> ; /// End Of VIDEO DATA ///
  2287                                  %include 'diskdata.s'	; DISK (BIOS) DATA (initialized)
  2288                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2289                              <1> ; Last Modification: 11/03/2015
  2290                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2291                              <1> ;
  2292                              <1> ; *****************************************************************************
  2293                              <1> 
  2294                              <1> ;----------------------------------------
  2295                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2296                              <1> ;	REFERENCED BY POST & BIOS	:
  2297                              <1> ;----------------------------------------
  2298                              <1> 
  2299 000069F8 [5B6A0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2300                              <1> 
  2301                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2302                              <1> ;----------------------------------------------------------------
  2303                              <1> ; DISK_BASE							:
  2304                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2305                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2306                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2307                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2308                              <1> ;----------------------------------------------------------------
  2309                              <1> 
  2310                              <1> ;DISK_BASE:	
  2311                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2312                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2313                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2314                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2315                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2316                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2317                              <1> ;	DB	01BH		; GAP LENGTH
  2318                              <1> ;	DB	0FFH		; DTL
  2319                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2320                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2321                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2322                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2323                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2324                              <1> 
  2325                              <1> ;----------------------------------------
  2326                              <1> ;	ROM BIOS DATA AREAS		:
  2327                              <1> ;----------------------------------------
  2328                              <1> 
  2329                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2330                              <1> 
  2331                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2332                              <1> 
  2333                              <1> ;----------------------------------------
  2334                              <1> ;	DISKETTE DATA AREAS		:
  2335                              <1> ;----------------------------------------
  2336                              <1> 
  2337                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2338                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2339                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2340                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2341                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2342                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2343                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2344                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2345                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2346                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2347                              <1> 
  2348                              <1> ;----------------------------------------
  2349                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2350                              <1> ;----------------------------------------
  2351                              <1> 
  2352                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2353                              <1> 
  2354                              <1> ;----------------------------------------
  2355                              <1> ;	TIMER DATA AREA 		:
  2356                              <1> ;----------------------------------------
  2357                              <1> 
  2358                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2359                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2360                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2361                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2362                              <1> 
  2363                              <1> ;----------------------------------------
  2364                              <1> ;	ADDITIONAL MEDIA DATA		:
  2365                              <1> ;----------------------------------------
  2366                              <1> 
  2367                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2368                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2369                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2370                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2371                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2372                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2373                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2374                              <1> 
  2375                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2376                              <1> 
  2377                              <1> ;--------------------------------------------------------
  2378                              <1> ;	DRIVE TYPE TABLE				:
  2379                              <1> ;--------------------------------------------------------
  2380                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2381                              <1> DR_TYPE:
  2382 000069FC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2383                              <1>                 ;DW	MD_TBL1
  2384 000069FD [1A6A0000]          <1> 		dd	MD_TBL1
  2385 00006A01 82                  <1> 		DB	02+BIT7ON
  2386                              <1> 		;DW	MD_TBL2
  2387 00006A02 [276A0000]          <1>                 dd      MD_TBL2
  2388 00006A06 02                  <1> DR_DEFAULT:	DB	02
  2389                              <1>                 ;DW	MD_TBL3
  2390 00006A07 [346A0000]          <1> 		dd      MD_TBL3
  2391 00006A0B 03                  <1> 		DB	03
  2392                              <1>                 ;DW	MD_TBL4
  2393 00006A0C [416A0000]          <1> 		dd      MD_TBL4
  2394 00006A10 84                  <1> 		DB	04+BIT7ON
  2395                              <1>                 ;DW	MD_TBL5
  2396 00006A11 [4E6A0000]          <1> 		dd      MD_TBL5
  2397 00006A15 04                  <1> 		DB	04
  2398                              <1>                 ;DW	MD_TBL6
  2399 00006A16 [5B6A0000]          <1> 		dd      MD_TBL6
  2400                              <1> DR_TYPE_E       equ $			; END OF TABLE
  2401                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2402                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2403                              <1> ;--------------------------------------------------------
  2404                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2405                              <1> ;--------------------------------------------------------
  2406                              <1> ;--------------------------------------------------------
  2407                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2408                              <1> ;--------------------------------------------------------
  2409                              <1> MD_TBL1:        
  2410 00006A1A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2411 00006A1B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2412 00006A1C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2413 00006A1D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2414 00006A1E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2415 00006A1F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2416 00006A20 FF                  <1> 	DB	0FFH		; DTL
  2417 00006A21 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2418 00006A22 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2419 00006A23 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2420 00006A24 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2421 00006A25 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2422 00006A26 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2423                              <1> ;--------------------------------------------------------
  2424                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2425                              <1> ;--------------------------------------------------------
  2426                              <1> MD_TBL2:        
  2427 00006A27 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2428 00006A28 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2429 00006A29 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2430 00006A2A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2431 00006A2B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2432 00006A2C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2433 00006A2D FF                  <1> 	DB	0FFH		; DTL
  2434 00006A2E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2435 00006A2F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2436 00006A30 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2437 00006A31 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2438 00006A32 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2439 00006A33 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2440                              <1> ;--------------------------------------------------------
  2441                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2442                              <1> ;--------------------------------------------------------
  2443                              <1> MD_TBL3:
  2444 00006A34 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2445 00006A35 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2446 00006A36 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2447 00006A37 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2448 00006A38 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2449 00006A39 1B                  <1> 	DB	01BH		; GAP LENGTH
  2450 00006A3A FF                  <1> 	DB	0FFH		; DTL
  2451 00006A3B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2452 00006A3C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2453 00006A3D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2454 00006A3E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2455 00006A3F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2456 00006A40 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2457                              <1> ;--------------------------------------------------------
  2458                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2459                              <1> ;--------------------------------------------------------
  2460                              <1> MD_TBL4:
  2461 00006A41 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2462 00006A42 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2463 00006A43 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2464 00006A44 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2465 00006A45 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2466 00006A46 2A                  <1> 	DB	02AH		; GAP LENGTH
  2467 00006A47 FF                  <1> 	DB	0FFH		; DTL
  2468 00006A48 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2469 00006A49 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2470 00006A4A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2471 00006A4B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2472 00006A4C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2473 00006A4D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2474                              <1> ;--------------------------------------------------------
  2475                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2476                              <1> ;--------------------------------------------------------
  2477                              <1> MD_TBL5:
  2478 00006A4E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2479 00006A4F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2480 00006A50 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2481 00006A51 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2482 00006A52 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2483 00006A53 2A                  <1> 	DB	02AH		; GAP LENGTH
  2484 00006A54 FF                  <1> 	DB	0FFH		; DTL
  2485 00006A55 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2486 00006A56 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2487 00006A57 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2488 00006A58 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2489 00006A59 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2490 00006A5A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2491                              <1> ;--------------------------------------------------------
  2492                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2493                              <1> ;--------------------------------------------------------
  2494                              <1> MD_TBL6:
  2495 00006A5B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2496 00006A5C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2497 00006A5D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2498 00006A5E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2499 00006A5F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2500 00006A60 1B                  <1> 	DB	01BH		; GAP LENGTH
  2501 00006A61 FF                  <1> 	DB	0FFH		; DTL
  2502 00006A62 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2503 00006A63 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2504 00006A64 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2505 00006A65 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2506 00006A66 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2507 00006A67 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2508                              <1> 
  2509                              <1> 
  2510                              <1> ; << diskette.inc >>
  2511                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2512                              <1> ;
  2513                              <1> ;----------------------------------------
  2514                              <1> ;	ROM BIOS DATA AREAS		:
  2515                              <1> ;----------------------------------------
  2516                              <1> 
  2517                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2518                              <1> 
  2519                              <1> ;----------------------------------------
  2520                              <1> ;	FIXED DISK DATA AREAS		:
  2521                              <1> ;----------------------------------------
  2522                              <1> 
  2523                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2524                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2525                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2526                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2527                              <1> 
  2528                              <1> ;----------------------------------------
  2529                              <1> ;	ADDITIONAL MEDIA DATA		:
  2530                              <1> ;----------------------------------------
  2531                              <1> 
  2532                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2533                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2534                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2535                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2536                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2537                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2538                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2539                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2540                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2541                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2542                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2543                              <1> 
  2544                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2545                              <1> ;
  2546                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2547                              <1> 
  2548                              <1> ERR_TBL:
  2549 00006A68 E0                  <1> 	db	NO_ERR
  2550 00006A69 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2551 00006A6D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2552                              <1> 
  2553                              <1> ; 17/12/2014 (mov ax, [cfd])
  2554                              <1> ; 11/12/2014
  2555 00006A71 00                  <1> cfd:		db	0		; current floppy drive (for GET_PARM)
  2556                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2557 00006A72 01                  <1> pfd:		db	1		; previous floppy drive (for GET_PARM)
  2558                              <1> 					; (initial value of 'pfd 
  2559                              <1> 					; must be different then 'cfd' value
  2560                              <1> 					; to force updating/initializing
  2561                              <1> 					; current drive parameters) 
  2562 00006A73 90                  <1> align 2
  2563                              <1> 
  2564 00006A74 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2565                              <1> 			      ; (170h)
  2566 00006A76 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2567                              <1> 
  2568                              <1> ; 05/01/2015 
  2569 00006A78 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2570                              <1> 
  2571                              <1> ; *****************************************************************************
  2288                                  ;;;
  2289                                  
  2290 00006A79 90                      align 2
  2291                                  
  2292                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2293 00006A7A 00                      boot_drv:    db 0  ; boot drive number (physical)
  2294                                  ; 24/11/2014
  2295 00006A7B 00                      drv:	     db 0 
  2296 00006A7C 00                      last_drv:    db 0  ; last hdd
  2297 00006A7D 00                      hdc:         db 0  ; number of hard disk drives
  2298                                  		     ; (present/detected)
  2299                                  ;
  2300                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2301                                  ; Physical drive type & flags
  2302 00006A7E 00                      fd0_type:    db 0  ; floppy drive type
  2303 00006A7F 00                      fd1_type:    db 0    ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2304                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2305                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2306                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2307                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2308 00006A80 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 - present flag)
  2309 00006A81 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 - present flag)
  2310 00006A82 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 - present flag)
  2311 00006A83 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 - present flag)
  2312                                  		     ; bit 0 - Fixed disk access subset supported
  2313                                  		     ; bit 1 - Drive locking and ejecting
  2314                                  		     ; bit 2 - Enhanced disk drive support
  2315                                  		     ; bit 3 - Reserved (64 bit EDD support)
  2316                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2317                                  		     ; will interpret it as 'LBA ready'!)		
  2318                                  
  2319                                  ; 11/03/2015 - 10/07/2015
  2320 00006A84 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2320 00006A8D 0000000000         
  2321 00006A92 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2321 00006A9B 0000000000         
  2322 00006AA0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2322 00006AA9 0000000000         
  2323 00006AAE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2323 00006AB7 000000000000000000-
  2323 00006AC0 000000000000000000-
  2323 00006AC9 00                 
  2324 00006ACA 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2325 00006AD1 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2326                                  ;
  2327                                  
  2328                                  ; 27/08/2014
  2329                                  scr_row:
  2330 00006AD8 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2331                                  scr_col:
  2332 00006ADC 00000000                	dd 0
  2333                                  
  2334                                  ;; 14/08/2015
  2335                                  ;;msgPM:
  2336                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2337                                  msgKVER:
  2338 00006AE0 526574726F20554E49-     	db "Retro UNIX 386 v1.2 - Kernel v0.2.2.0 [16/02/2022]", 0
  2338 00006AE9 58203338362076312E-
  2338 00006AF2 32202D204B65726E65-
  2338 00006AFB 6C2076302E322E322E-
  2338 00006B04 30205B31362F30322F-
  2338 00006B0D 323032325D00       
  2339                                  
  2340 00006B13 90                      align 2
  2341                                  
  2342                                  ; 20/08/2014
  2343                                    ; /* This is the default interrupt "handler" :-) */ 
  2344                                    ; Linux v0.12 (head.s)
  2345                                  int_msg:
  2346 00006B14 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2346 00006B1D 6E7465727275707420-
  2346 00006B26 212000             
  2347                                  
  2348 00006B29 90                      align 2  
  2349                                  
  2350                                  ; 21/08/2014
  2351                                  timer_msg:
  2352 00006B2A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2352 00006B33 542032306829202120-
  2352 00006B3C 54696D657220496E74-
  2352 00006B45 657272757074203A20 
  2353                                  tcountstr:
  2354 00006B4E 303030303020            	db "00000 "
  2355 00006B54 00                      	db 0
  2356                                  
  2357 00006B55 90                      align 2
  2358                                  	; 21/08/2014
  2359                                  exc_msg:
  2360 00006B56 435055206578636570-     	db "CPU exception ! "
  2360 00006B5F 74696F6E202120     
  2361                                  excnstr: 		; 25/08/2014
  2362 00006B66 3F3F68202045495020-     	db "??h", "  EIP : "
  2362 00006B6F 3A20               
  2363                                  EIPstr: ; 29/08/2014
  2364 00006B71 00<rep Ch>              	times 12 db 0
  2365                                  rtc_msg:
  2366 00006B7D 5265616C2054696D65-     	db "Real Time Clock - "
  2366 00006B86 20436C6F636B202D20 
  2367                                  datestr:
  2368 00006B8F 30302F30302F303030-     	db "00/00/0000"
  2368 00006B98 30                 
  2369 00006B99 20                      	db " "
  2370                                  daystr:
  2371 00006B9A 44415920                	db "DAY "
  2372                                  timestr:	
  2373 00006B9E 30303A30303A3030                db "00:00:00"
  2374 00006BA6 20                      	db " "
  2375 00006BA7 00                      	db 0 
  2376                                  
  2377                                  daytmp:
  2378                                  	; 28/02/2015
  2379 00006BA8 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2379 00006BB1 4F4E20545545205745-
  2379 00006BBA 442054485520465249-
  2379 00006BC3 2053415420         
  2380                                  
  2381 00006BC8 FF                      ptime_seconds: db 0FFh
  2382                                  
  2383                                  	; 23/02/2015
  2384                                  	; 25/08/2014
  2385                                  ;scounter:
  2386                                  ;	db 5
  2387                                  ;	db 19
  2388                                  
  2389                                  ; 28/11/2021
  2390                                  ;; 05/11/2014
  2391                                  ;msg_out_of_memory:
  2392                                  ;	db 	07h, 0Dh, 0Ah
  2393                                  ;	db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2394                                  ; 	db	0Dh, 0Ah, 0
  2395                                  	;
  2396                                  setup_error_msg:
  2397 00006BC9 0D0A                    	db 0Dh, 0Ah
  2398 00006BCB 4469736B2053657475-     	db 'Disk Setup Error!' 
  2398 00006BD4 70204572726F7221   
  2399 00006BDC 0D0A00                  	db 0Dh, 0Ah,0
  2400                                  
  2401                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2402                                  ;crt_ulc: db 0 ; upper left column (for scroll) 
  2403                                  ;	  db 0 ; upper left row (for scroll)	
  2404                                  
  2405                                  ;crt_lrc: db 79 ; lower right column (for scroll) 
  2406                                  ;	  db 24 ; lower right row (for scroll)
  2407                                  
  2408                                  ; 06/11/2014 (Temporary Data)
  2409                                  ; Memory Information message
  2410                                  ; 14/08/2015
  2411                                  msg_memory_info:
  2412 00006BDF 07                      	db	07h
  2413 00006BE0 0D0A                    	db	0Dh, 0Ah
  2414                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2415 00006BE2 546F74616C206D656D-     	db	"Total memory : "
  2415 00006BEB 6F7279203A20       
  2416                                  mem_total_b_str: ; 10 digits
  2417 00006BF1 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2417 00006BFA 302062797465730D0A 
  2418 00006C03 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2418 00006C0C 202020202020202020 
  2419                                  mem_total_p_str: ; 7 digits
  2420 00006C15 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2420 00006C1E 616765730D0A       
  2421 00006C24 0D0A                    	db 	0Dh, 0Ah
  2422 00006C26 46726565206D656D6F-     	db	"Free memory  : "
  2422 00006C2F 727920203A20       
  2423                                  free_mem_b_str:  ; 10 digits
  2424 00006C35 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2424 00006C3E 3F2062797465730D0A 
  2425 00006C47 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2425 00006C50 202020202020202020 
  2426                                  free_mem_p_str:  ; 7 digits
  2427 00006C59 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2427 00006C62 616765730D0A       
  2428 00006C68 0D0A00                  	db	0Dh, 0Ah, 0
  2429                                  
  2430                                  dsk_ready_msg:
  2431 00006C6B 0D0A                    	db 	0Dh, 0Ah
  2432                                  dsktype:
  2433 00006C6D 6664                    	db	'fd'
  2434                                  dskx:
  2435 00006C6F 30                      	db	'0'
  2436 00006C70 20                      	db	20h
  2437 00006C71 697320524541445920-     	db 	'is READY ...'
  2437 00006C7A 2E2E2E             
  2438 00006C7D 00                      	db 	0
  2439                                  nextline:
  2440 00006C7E 0D0A00                  	db 	0Dh, 0Ah, 0
  2441                                  
  2442                                  ; KERNEL - SYSINIT Messages
  2443                                  ; 24/08/2015
  2444                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2445                                  ; 14/07/2013
  2446                                  ;kernel_init_err_msg:
  2447                                  ;	db 0Dh, 0Ah
  2448                                  ;	db 07h
  2449                                  ;	db 'Kernel initialization ERROR !'
  2450                                  ;	db 0Dh, 0Ah, 0 
  2451                                  ; 24/08/2015
  2452                                  ;;; (temporary kernel init message has been removed
  2453                                  ;;;  from 'sys_init' code)
  2454                                  ;kernel_init_ok_msg: 
  2455                                  ;	db 0Dh, 0Ah
  2456                                  ;	db 07h
  2457                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2458                                  ;	db 0Dh, 0Ah
  2459                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2460                                  ;	db 0Dh, 0Ah, 0
  2461                                  panic_msg:
  2462 00006C81 0D0A07                  	db 0Dh, 0Ah, 07h
  2463 00006C84 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2463 00006C8D 726E656C2050616E69-
  2463 00006C96 632021             
  2464 00006C99 0D0A00                  	db 0Dh, 0Ah, 0
  2465                                  etc_init_err_msg:
  2466 00006C9C 0D0A                    	db 0Dh, 0Ah
  2467 00006C9E 07                      	db 07h
  2468 00006C9F 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2468 00006CA8 74632F696E69742021-
  2468 00006CB1 3F                 
  2469 00006CB2 0D0A00                  	db 0Dh, 0Ah, 0
  2470                                  
  2471                                  ; 10/05/2015
  2472                                  badsys_msg:
  2473 00006CB5 0D0A                    	db 0Dh, 0Ah
  2474 00006CB7 07                      	db 07h
  2475 00006CB8 496E76616C69642053-     	db 'Invalid System Call !'
  2475 00006CC1 797374656D2043616C-
  2475 00006CCA 6C2021             
  2476 00006CCD 0D0A                    	db 0Dh, 0Ah
  2477 00006CCF 4541583A20              	db 'EAX: '
  2478                                  bsys_msg_eax:
  2479 00006CD4 303030303030303068      	db '00000000h'
  2480 00006CDD 0D0A                    	db 0Dh, 0Ah
  2481 00006CDF 4549503A20              	db 'EIP: '
  2482                                  bsys_msg_eip:
  2483 00006CE4 303030303030303068      	db '00000000h' 
  2484 00006CED 0D0A00                  	db 0Dh, 0Ah, 0
  2485                                  
  2486                                  BSYS_M_SIZE equ $ - badsys_msg
  2487                                  
  2488                                  align 2
  2489                                  
  2490                                  ; EPOCH Variables
  2491                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2492                                  ; 09/04/2013 epoch variables
  2493                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2494                                  ;
  2495 00006CF0 B207                    year: 	dw 1970
  2496 00006CF2 0100                    month: 	dw 1
  2497 00006CF4 0100                    day: 	dw 1
  2498 00006CF6 0000                    hour: 	dw 0
  2499 00006CF8 0000                    minute: dw 0
  2500 00006CFA 0000                    second: dw 0
  2501                                  
  2502                                  DMonth:
  2503 00006CFC 0000                    	dw 0
  2504 00006CFE 1F00                    	dw 31
  2505 00006D00 3B00                    	dw 59
  2506 00006D02 5A00                    	dw 90
  2507 00006D04 7800                    	dw 120
  2508 00006D06 9700                    	dw 151
  2509 00006D08 B500                    	dw 181
  2510 00006D0A D400                    	dw 212
  2511 00006D0C F300                    	dw 243
  2512 00006D0E 1101                    	dw 273
  2513 00006D10 3001                    	dw 304
  2514 00006D12 4E01                    	dw 334
  2515                                  
  2516                                  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2517                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2518 00006D14 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2519                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2520 00006D16 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2521 00006D18 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2522                                  		   ;   between 16 MB and 4 GB.
  2523 00006D1A 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2524                                  
  2525                                  ; 01/01/2022
  2526                                  KEND:
  2527                                  
  2528 00006D1C 90<rep 4h>              align 16
  2529                                  
  2530                                  bss_start:
  2531                                  
  2532                                  ABSOLUTE bss_start
  2533                                  
  2534                                  	; 11/03/2015
  2535                                  	; Interrupt Descriptor Table (20/08/2014)
  2536                                  idt:
  2537 00006D20 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2538                                  idt_end:
  2539                                  
  2540                                  ;alignb 4
  2541                                  
  2542                                  task_state_segment:
  2543                                  	; 24/03/2015
  2544 00006F20 ????                    tss.link:   resw 1
  2545 00006F22 ????                    	    resw 1
  2546                                  ; tss offset 4	
  2547 00006F24 ????????                tss.esp0:   resd 1
  2548 00006F28 ????                    tss.ss0:    resw 1
  2549 00006F2A ????                    	    resw 1	
  2550 00006F2C ????????                tss.esp1:   resd 1
  2551 00006F30 ????                    tss.ss1:    resw 1
  2552 00006F32 ????                    	    resw 1 	
  2553 00006F34 ????????                tss.esp2:   resd 1
  2554 00006F38 ????                    tss.ss2:    resw 1
  2555 00006F3A ????                    	    resw 1
  2556                                  ; tss offset 28
  2557 00006F3C ????????                tss.CR3:    resd 1
  2558 00006F40 ????????                tss.eip:    resd 1
  2559 00006F44 ????????                tss.eflags: resd 1
  2560                                  ; tss offset 40
  2561 00006F48 ????????                tss.eax:    resd 1		 		
  2562 00006F4C ????????                tss.ecx:    resd 1
  2563 00006F50 ????????                tss.edx:    resd 1
  2564 00006F54 ????????                tss.ebx:    resd 1
  2565 00006F58 ????????                tss.esp:    resd 1
  2566 00006F5C ????????                tss.ebp:    resd 1
  2567 00006F60 ????????                tss.esi:    resd 1
  2568 00006F64 ????????                tss.edi:    resd 1
  2569                                  ; tss offset 72
  2570 00006F68 ????                    tss.ES:     resw 1
  2571 00006F6A ????                    	    resw 1	
  2572 00006F6C ????                    tss.CS:	    resw 1
  2573 00006F6E ????                    	    resw 1
  2574 00006F70 ????                    tss.SS:	    resw 1
  2575 00006F72 ????                    	    resw 1
  2576 00006F74 ????                    tss.DS:	    resw 1
  2577 00006F76 ????                    	    resw 1
  2578 00006F78 ????                    tss.FS:	    resw 1
  2579 00006F7A ????                    	    resw 1
  2580 00006F7C ????                    tss.GS:	    resw 1
  2581 00006F7E ????                    	    resw 1		
  2582 00006F80 ????                    tss.LDTR:   resw 1
  2583 00006F82 ????                    	    resw 1
  2584                                  ; tss offset 100		
  2585 00006F84 ????                    	    resw 1		
  2586 00006F86 ????                    tss.IOPB:   resw 1
  2587                                  ; tss offset 104 
  2588                                  tss_end:
  2589                                  
  2590 00006F88 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2591                                  		    ;  (Physical address = Virtual address)	 	
  2592 00006F8C ????????                memory_size: resd 1 ; memory size in pages
  2593 00006F90 ????????                free_pages:  resd 1 ; number of free pages		
  2594 00006F94 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2595                                  		    ;   first free page search
  2596 00006F98 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2597                                  		    ;   next free page search will be
  2598                                  		    ;   stopped after it. (end of M.A.T.)
  2599 00006F9C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2600                                  		    ; first free page search
  2601                                  		    ;   will be started on it. (for user)
  2602 00006FA0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2603                                  
  2604                                  ;;;
  2605                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2606                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2607 00006FA4 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2608                                  			  ; NOTE: active page only
  2609 00006FA6 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2610                                  active_page: 
  2611 00006FB6 ??                      ptty: 	     resb 1 	  ; current tty
  2612                                  ; 01/07/2015
  2613 00006FB7 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2614                                  ; 26/10/2015
  2615                                  ; 07/09/2014
  2616 00006FB8 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2617                                  
  2618                                  ; 21/08/2014
  2619 00006FCC ????????                tcount:	     resd 1
  2620                                  
  2621                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2622 00006FD0 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2623                                  
  2624                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2625                                  ; (open mode locks for pseudo TTYs)
  2626                                  ; [ major tty locks (return error in any conflicts) ]
  2627 00006FD4 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2628                                  
  2629                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2630                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2631 00006FE8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2632                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2633                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2634                                  ;; 0 means serial port is not available 
  2635                                  ;;comprm: ; 25/06/2014
  2636 00006FF2 ??                      com1p:       resb 1  ;;0E3h
  2637 00006FF3 ??                      com2p:       resb 1  ;;0E3h
  2638                                  
  2639                                  ; 17/11/2015
  2640                                  ; request for response (from the terminal)	
  2641 00006FF4 ????                    req_resp:    resw 1 			
  2642                                  ; 07/11/2015
  2643 00006FF6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2644                                  		    ; (0= COM1, 1= COM2)
  2645                                  ; 09/11/2015
  2646 00006FF7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2647                                  ; 07/11/2015
  2648 00006FF8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2649 00006FFA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2650                                  
  2651                                  ; 23/10/2015
  2652                                  ; SERIAL PORTS - COMMUNICATION MODES
  2653                                  ; (Retro UNIX 386 v1 feature only!)
  2654                                  ; 0 - command mode (default/initial mode)
  2655                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2656                                  ;;; communication modes for future versions:  
  2657                                  ; // 2 - keyboard mode (ascii+scancode input)
  2658                                  ; // 3 - mouse mode
  2659                                  ; // 4 - device control (output) mode
  2660                                  ; VALID COMMANDS for current version:
  2661                                  ; 	'LOGIN'
  2662                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2663                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2664                                  ;  Login response: db 0FFh, 'login', 0
  2665                                  ;	 ("login request accepted, wait for login prompt") 
  2666                                  ; When a login requests is received and acknowledged (by
  2667                                  ; serial port interrupt handler (communication procedure),
  2668                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2669                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2670                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2671                                  ; 
  2672                                  ; 'sys connect' system call is used to change communication mode
  2673                                  ; except 'LOGIN' command which is used to start terminal mode
  2674                                  ; by using (COM port) terminal.
  2675                                  
  2676                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2677                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2678                                  ;com1mode:    resb 1 ; communication mode for COM1
  2679                                  ;com1com:     resb 1 ; communication command for COM1
  2680                                  ;com2mode:    resb 1 ; communication mode for COM1
  2681                                  ;com2com      resb 1 ; communication command for COM1
  2682                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2683                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2684                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2685                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2686                                  
  2687                                  ; 22/08/2014 (RTC)
  2688                                  ; (Packed BCD)
  2689 00006FFC ??                      time_seconds: resb 1
  2690 00006FFD ??                      time_minutes: resb 1
  2691 00006FFE ??                      time_hours:   resb 1
  2692 00006FFF ??                      date_wday:    resb 1
  2693 00007000 ??                      date_day:     resb 1
  2694 00007001 ??                      date_month:   resb 1			
  2695 00007002 ??                      date_year:    resb 1
  2696 00007003 ??                      date_century: resb 1
  2697                                  
  2698                                  %include 'diskbss.s' ; UNINITIALIZED DISK (BIOS) DATA
  2699                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2700                              <1> ; Last Modification: 10/07/2015
  2701                              <1> ;	(Unitialized Disk Parameters Data section for 'DISKIO.INC') 
  2702                              <1> ;
  2703                              <1> ; *****************************************************************************
  2704                              <1> 
  2705                              <1> alignb 2
  2706                              <1> 
  2707                              <1> ;----------------------------------------
  2708                              <1> ;	TIMER DATA AREA 		:
  2709                              <1> ;----------------------------------------
  2710                              <1> 
  2711                              <1> TIMER_LH:	; 16/02/2015
  2712 00007004 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2713 00007006 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2714 00007008 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2715                              <1> 
  2716                              <1> ;----------------------------------------
  2717                              <1> ;	DISKETTE DATA AREAS		:
  2718                              <1> ;----------------------------------------
  2719                              <1> 
  2720 00007009 ??                  <1> SEEK_STATUS:	resb	1
  2721 0000700A ??                  <1> MOTOR_STATUS:	resb	1
  2722 0000700B ??                  <1> MOTOR_COUNT:	resb	1
  2723 0000700C ??                  <1> DSKETTE_STATUS:	resb	1
  2724 0000700D ??????????????      <1> NEC_STATUS:	resb	7
  2725                              <1> 
  2726                              <1> ;----------------------------------------
  2727                              <1> ;	ADDITIONAL MEDIA DATA		:
  2728                              <1> ;----------------------------------------
  2729                              <1> 
  2730 00007014 ??                  <1> LASTRATE:	resb 	1
  2731 00007015 ??                  <1> HF_STATUS:	resb 	1
  2732 00007016 ??                  <1> HF_ERROR:	resb 	1
  2733 00007017 ??                  <1> HF_INT_FLAG:	resb 	1
  2734 00007018 ??                  <1> HF_CNTRL:	resb 	1
  2735 00007019 ????????            <1> DSK_STATE:	resb 	4
  2736 0000701D ????                <1> DSK_TRK:	resb 	2
  2737                              <1> 
  2738                              <1> ;----------------------------------------
  2739                              <1> ;	FIXED DISK DATA AREAS		:
  2740                              <1> ;----------------------------------------
  2741                              <1> 
  2742 0000701F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2743 00007020 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2744 00007021 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2745                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2746                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2747                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2748                              <1> 
  2749 00007022 ????                <1> alignb 4
  2750                              <1> 
  2751                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2752                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2753                              <1> HF_TBL_VEC: ; 22/12/2014	
  2754 00007024 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2755 00007028 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2756 0000702C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2757 00007030 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2758                              <1> 
  2759                              <1> ; 03/01/2015
  2760 00007034 ??                  <1> LBAMode:     	resb	1
  2761                              <1> 
  2762                              <1> ; *****************************************************************************
  2699                                  
  2700                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2701                                  
  2702                                  ;alignb 2
  2703                                  
  2704                                  ; 02/01/2022
  2705                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2706                                  
  2707                                  ; 17/04/2021
  2708                                  ; (memory page swap parameters are disabled as temporary)
  2709                                  ;
  2710                                  ;; Memory (swap) Data (11/03/2015)
  2711                                  ; 09/03/2015
  2712                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2713                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2714                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2715                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2716                                  ;swpd_next:  resd 1 ; next free page block
  2717                                  ;swpd_last:  resd 1 ; last swap page block	
  2718                                  
  2719 00007035 ??????                  alignb 4
  2720                                  
  2721                                  ; 10/07/2015
  2722                                  ; 28/08/2014
  2723 00007038 ????????                error_code:  resd 1
  2724                                  ; 29/08/2014
  2725 0000703C ????????                FaultOffset: resd 1
  2726                                  ; 21/09/2015
  2727 00007040 ????????                PF_Count:    resd 1 ; total page fault count
  2728                                  		    ; (for debugging - page fault analyze)
  2729                                  		    ; 'page _fault_handler' (memory.s)
  2730                                  		    ; 'sysgeterr' (u9.s)
  2731                                  ;; 21/08/2015
  2732                                  ;;buffer: resb (nbuf*520) ;; sysdefs.s, ux.s
  2733                                  
  2734                                  ; 02/01/2022
  2735                                  %include 'ux.s'	; 12/04/2015 (unix system/user/process data)
  2736                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2737                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2738                              <1> ; ****************************************************************************
  2739                              <1> ; Retro UNIX 386 v1.2 Kernel - ux.s
  2740                              <1> ; Last Modification: 12/01/2022
  2741                              <1> ;
  2742                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2743                              <1> ; (Modified from 
  2744                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2745                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2746                              <1> ; ----------------------------------------------------------------------------
  2747                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2748                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2749                              <1> ; <Bell Laboratories (17/3/1972)>
  2750                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2751                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2752                              <1> ; ****************************************************************************
  2753                              <1> 
  2754                              <1> ; 22/11/2021 (Modification in Runix v1.1 'ux.s' for runix v2 fs compatibility)
  2755                              <1> ; 18/07/2021
  2756                              <1> ; 15/07/2021
  2757                              <1> ; 12/05/2021
  2758                              <1> ; 09/05/2021
  2759                              <1> ; 06/05/2021
  2760                              <1> ; 02/05/2021
  2761                              <1> ; 26/01/2020 (NASM version of SuperBlock structure in UNIXHDCP.ASM)
  2762                              <1> 
  2763                              <1> ; 21/12/2019 (UNIXCOPY.COM, UNIXCOPY.ASM, UNIXHDCP.COM, UNIXHDCP.ASM)
  2764                              <1> ; 19/12/2019 (UNIXHDFS.COM, RUFSHDI.ASM)
  2765                              <1> ; 01/09/2019 - Retro UNIX 386 v2 SuperBlock
  2766                              <1> 
  2767                              <1> ; 14/01/2020 - Super Block modification:
  2768                              <1> ;	     - Extended sections/divisions (consequental sectors)
  2769                              <1> ;	     - (for swapping, configuration, boot space etc.)	
  2770                              <1> 
  2771                              <1> ; 26/01/2020 (unix386.s, ux.s)
  2772                              <1> ; 14/01/2020
  2773                              <1> SB.HiddenSects	equ SB.BootSectAddr
  2774                              <1> SB.TotalSects	equ SB.VolumeSize
  2775                              <1> 
  2776                              <1> ; 11/05/2021 (Retro UNIX 386 v2)
  2777                              <1> ; Super block status byte (byte 0 of SB.status dword)
  2778                              <1> ; 	bit 0 - superblock modified flag
  2779                              <1> ; 	bit 1 - inode map modified flag
  2780                              <1> ; 	bit 2 - free blocks map modified flag
  2781                              <1> ; 	bit 3 - inode table modified flag
  2782                              <1> ;; 	bit 4 - boot sector modified flag ; 17/08/2021
  2783                              <1> ; 17/08/2021
  2784                              <1> ;	bit 4 - file data write error (for SB.LastInode)
  2785                              <1> ;	bit 5 - inode table write error (for SB.LastInode)
  2786                              <1> ;	bit 6 - inode map write error (for SB.LastInode)
  2787                              <1> ;	bit 7 - free blocks map write error (for SB.LastInode)
  2788                              <1> 	
  2789                              <1> ; 21/12/2019
  2790                              <1> ; 19/12/2019 - Retro UNIX 386 v2 HD (071h) partition boot sector 
  2791                              <1> ;	       (UNIXHDFS.ASM)
  2792                              <1> ; 04/12/2015 (14 byte file names - Retro UNIX 386 v1.1)
  2793                              <1> ; 14/07/2015 (8 byte file names - Retro UNIX 8086 v1 & Retro UNIX 386 v1.0)
  2794                              <1> 
  2795                              <1> bsFSystemID 	equ 2  ; db 'RUFS'	
  2796                              <1> bsVolumeSerial 	equ 6  ; dd 0 ; (4 bytes)
  2797                              <1> bsFDSign	equ 10 ; db 'fd'
  2798                              <1> bsDriveNumber 	equ 12 ; db 0 ; fd0 or fd1 (0 or 1)
  2799                              <1> bsReserved 	equ 13 ; db 0 ; (512 bytes per sector)	
  2800                              <1> bsSecPerTrack	equ 14 ; db 18 ; (9 or 15)	
  2801                              <1> bsHeads		equ 15 ; db  ; 2
  2802                              <1> bsTracks	equ 16 ; dw 80 ; bsCylinders
  2803                              <1> bs_bf_inode_number equ 18 ; dw 0 ; 0 or Boot/Startup File I-Number
  2804                              <1> bsInfoEndsign	equ 20 ; db '@'
  2805                              <1> ; 21/12/2019
  2806                              <1> bsMagic		equ 20 ; db '@'
  2807                              <1> bsPartitionID	equ 21 ; db 0 ; db 71h
  2808                              <1> bsHiddenSects	equ 22 ; dd 0 ; Hidden sectors (Boot Sector LBA)
  2809                              <1> 
  2810                              <1> ; 22/11/2021 - Retro UNIX v2 I-node Flags
  2811                              <1> ; ------------------------------------------------------------------
  2812                              <1> ; UINSTALL.ASM (included in UNIXFDFS.ASM) - 23/01/2020
  2813                              <1> ; ------------------------------------------------------------------
  2814                              <1> 
  2815                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  2816                              <1> ; 1000000000000000b 	IFREG - 1 = regular file (8000h)
  2817                              <1> ; 0100000000000000b	IFDIR - 1 = directory (4000h)
  2818                              <1> ; 0010000000000000b	IRSVD - 0 = reserved bit (2000h) ; Mounted flag
  2819                              <1> ; 0001000000000000b	ILARG - large file addressing bit (1000h)
  2820                              <1> ; 0000100000000000b	ISUID - set user id on exec (800h)
  2821                              <1> ; 0000010000000000b	ISGID - set group id on exec (400h)
  2822                              <1> ; 0000001000000000b	IEXTT - 1 = use extents (200h)
  2823                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2824                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2825                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2826                              <1> ; 0000000000100000b	read, group (20h)
  2827                              <1> ; 0000000000010000b	write, group (10h)
  2828                              <1> ; 0000000000001000b	execute, group (08h)
  2829                              <1> ; 0000000000000100b	read, others (04h)
  2830                              <1> ; 0000000000000010b	write, others (02h)
  2831                              <1> ; 0000000000000001b	execute, others (01h)
  2832                              <1> 
  2833                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  2834                              <1> ; 1000000000000000b 	IFREG - 0 = device file (8000h)
  2835                              <1> ; 0100000000000000b	IFBLK - 1 = block device (4000h)
  2836                              <1> ; 0010000000000000b	IFCHR - character special (2000h) -always 1-
  2837                              <1> ; 0001000000000000b	IFIFO - fifo special (1000h)
  2838                              <1> ; 0000100000000000b	IPIPE - pipe special (800h) ; 07/02/2020
  2839                              <1> ; 0000010000000000b	IREDIR - redirected (400h)  ; 07/02/2020
  2840                              <1> ; 0000001000000000b	IEXTR - 1 = external device driver (200h)
  2841                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2842                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2843                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2844                              <1> ; 0000000000100000b	read, group (20h)
  2845                              <1> ; 0000000000010000b	write, group (10h)
  2846                              <1> ; 0000000000001000b	execute, group (08h)
  2847                              <1> ; 0000000000000100b	read, others (04h)
  2848                              <1> ; 0000000000000010b	write, others (02h)
  2849                              <1> ; 0000000000000001b	execute, others (01h)
  2850                              <1> 
  2851                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  2852                              <1> ; (SB structure has been moved from here to 'sysdefs.s'
  2853                              <1> ;	to overcome NASM's bss addressing bug !!!)
  2854                              <1> ; (('ux.s' bss section addresses are being overlapped
  2855                              <1> ;    when SB structure is defined in 'ux.s'))
  2856                              <1> 
  2857                              <1> %if 0
  2858                              <1> 
  2859                              <1> struc SB ; SuperBlock
  2860                              <1> 
  2861                              <1> .Header:	resd 1
  2862                              <1> ;.HiddenSects:
  2863                              <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2864                              <1> ;.TotalSects:
  2865                              <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)
  2866                              <1> .Version:	resd 1	
  2867                              <1> .BlockSize:	resd 1	
  2868                              <1> .InodeCount:	resd 1	
  2869                              <1> .FreeMapAddr:	resd 1	
  2870                              <1> .FreeMapSize:	resd 1	
  2871                              <1> .InodeMapAddr:	resd 1	
  2872                              <1> .InodeMapSize:	resd 1	
  2873                              <1> .InodeTblAddr:	resd 1	
  2874                              <1> .InodeTblSize:	resd 1	
  2875                              <1> .FreeInodes:	resd 1	
  2876                              <1> .FirstFreeIno:	resd 1	
  2877                              <1> .FreeBlocks:	resd 1	
  2878                              <1> .FirstFreeBlk:	resd 1	
  2879                              <1> .BootSecParms:	resb 19	; v1
  2880                              <1> .BSExtension:	resb 5	; v2 HDFS
  2881                              <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2882                              <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2883                              <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2884                              <1> .ModifTime:	resd 1	; (last) modification time (*)
  2885                              <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2886                              <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2887                              <1> .LBA_rw:	resb 1
  2888                              <1> .ClusterSize:	resb 1
  2889                              <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2890                              <1> .Mounted:	resb 1
  2891                              <1> .MountInode:	resd 1  ; double word
  2892                              <1> .DevMajor:	resb 1
  2893                              <1> .DevMinor:	resb 1
  2894                              <1> .LongName:	resb 1
  2895                              <1> .Direntry32:	resb 1
  2896                              <1> ; 18/07/2021
  2897                              <1> .FileBuffer:	resd 1
  2898                              <1> .ItabBuffer:	resd 1
  2899                              <1> .ImapBuffer:	resd 1
  2900                              <1> .FmapBuffer:	resd 1
  2901                              <1>  ; 15/07/2021
  2902                              <1> .LastInode:	resd 1
  2903                              <1> ; 02/05/2021
  2904                              <1> .FmapIndex:	resd 1
  2905                              <1> .ImapIndex:	resd 1
  2906                              <1> .ItableIndex:	resd 1
  2907                              <1> .Reserved:	resb 508-148 ; 18/07/2021
  2908                              <1> .Footer:	resd 1
  2909                              <1> 
  2910                              <1> endstruc
  2911                              <1> 
  2912                              <1> %endif
  2913                              <1> 
  2914                              <1> alignb 2
  2915                              <1> 
  2916                              <1> inode:
  2917                              <1> 	;; 11/03/2013. 
  2918                              <1> 	;;Derived from UNIX v1 source code 'inode' structure (ux).
  2919                              <1> 	;;i.
  2920                              <1> 	;
  2921                              <1> 	;i.flgs: resw 1
  2922                              <1> 	;i.nlks: resb 1
  2923                              <1> 	;i.uid:	 resb 1
  2924                              <1>         ;i.size: resw 1 ; size
  2925                              <1> 	;i.dskp: resw 8 ; 16 bytes
  2926                              <1> 	;i.ctim: resd 1
  2927                              <1> 	;i.mtim: resd 1
  2928                              <1> 	;i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1)
  2929                              <1> 
  2930                              <1> 	; 26/01/2020
  2931                              <1> 	; Retro UNIX 386 v2.0 - Modified UNIX v7 inode model
  2932                              <1> 	;	(15/09/2029 .. 18/12/2019)
  2933                              <1> 
  2934 00007044 ????                <1> 	i.flgs:   resw 1	; /* mode and type of file */
  2935 00007046 ????                <1> 	i.nlks:	  resw 1	; /* number of links to file */
  2936 00007048 ????                <1> 	i.uid:	  resw 1	; /* owner's user id */  - 0 to 655535 -
  2937 0000704A ??                  <1> 	i.gid:	  resb 1	; /* owner's group id */ - o to 255 -
  2938 0000704B ??                  <1> 	i.size_h: resb 1	; /* number of bytes in file */ ; byte 5
  2939 0000704C ????????            <1> 	i.size:	  resd 1 ; size	; /* number of bytes in file */
  2940 00007050 <res 28h>           <1> 	i.dskp:	  resd 10 ; 40 bytes ; /* disk block addresses */
  2941 00007078 ????????            <1> 	i.atim:	  resd 1	; /* time last accessed */
  2942 0000707C ????????            <1> 	i.mtim:	  resd 1	; /* time last modified */
  2943 00007080 ????????            <1> 	i.ctim:	  resd 1	; /* time created */
  2944                              <1> 
  2945                              <1> I_SIZE	equ $ - inode
  2946                              <1> 
  2947                              <1> process:
  2948                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.2) 
  2949                              <1> 	; 06/05/2015
  2950                              <1> 	; 11/03/2013 - 05/02/2014
  2951                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2952                              <1> 	;p.
  2953                              <1> 	
  2954 00007084 <res 20h>           <1>         p.pid:   resw nproc
  2955 000070A4 <res 20h>           <1>         p.ppid:  resw nproc
  2956                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2957 000070C4 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2958 000070D4 <res 10h>           <1> 	p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2959 000070E4 <res 10h>           <1> 	p.link:	 resb nproc
  2960 000070F4 <res 10h>           <1> 	p.stat:	 resb nproc
  2961                              <1> 
  2962                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 feature only !) 
  2963 00007104 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2964                              <1> 			    ; 'user' structure	
  2965                              <1> 
  2966                              <1> P_SIZE	equ $ - process
  2967                              <1> 
  2968                              <1> ; fsp table (original UNIX v1)
  2969                              <1> ;
  2970                              <1> ;Entry
  2971                              <1> ;          15                                      0
  2972                              <1> ;  1     |---|---------------------------------------|
  2973                              <1> ;        |r/w|       i-number of open file           |
  2974                              <1> ;        |---|---------------------------------------| 
  2975                              <1> ;        |               device number               |
  2976                              <1> ;        |-------------------------------------------|
  2977                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2978                              <1> ;        |-------------------------------------------| 
  2979                              <1> ;        |  flag that says    | number of processes  |
  2980                              <1> ;        |   file deleted     | that have file open  |
  2981                              <1> ;        |-------------------------------------------| 
  2982                              <1> ;  2     |                                           |
  2983                              <1> ;        |-------------------------------------------| 
  2984                              <1> ;        |                                           |
  2985                              <1> ;        |-------------------------------------------|
  2986                              <1> ;        |                                           |
  2987                              <1> ;        |-------------------------------------------|
  2988                              <1> ;        |                                           |
  2989                              <1> ;        |-------------------------------------------| 
  2990                              <1> ;  3     |                                           | 
  2991                              <1> ;        |                                           |  
  2992                              <1> ;
  2993                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2994                              <1> 
  2995                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  2996                              <1> 
  2997                              <1> ;Entry
  2998                              <1> ;         15                    7                   0
  2999                              <1> ;  1     |-------------------------------------------|
  3000                              <1> ;        |   	     i-number of open file           |
  3001                              <1> ;        |-------------------------------------------| 
  3002                              <1> ;        |        high word of 32 bit i-number       |
  3003                              <1> ;        |-------------------------------------------|
  3004                              <1> ;        | open mode & status  |   device number     |
  3005                              <1> ;        |-------------------------------------------|
  3006                              <1> ;        |    reserved byte    |     open count      |
  3007                              <1> ;        |-------------------------------------------| 
  3008                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3009                              <1> ;        |-------------------------------------------|
  3010                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3011                              <1> ;        |-------------------------------------------|
  3012                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3013                              <1> ;        |-------------------------------------------|
  3014                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3015                              <1> ;        |-------------------------------------------|
  3016                              <1> ;  2     |                                           |
  3017                              <1> ;        |-------------------------------------------| 
  3018                              <1> ;        |                                           |
  3019                              <1> ;        |-------------------------------------------|
  3020                              <1> ;        |                                           |
  3021                              <1> ;        |-------------------------------------------|
  3022                              <1> ;        |                                           |
  3023                              <1> ;        |-------------------------------------------| 
  3024                              <1> ;        |                                           | 
  3025                              <1> 
  3026                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  3027                              <1> ; (file structure has been moved from here to 'sysdefs.s'
  3028                              <1> ;	to overcome NASM's bss addressing bug !!!)
  3029                              <1> ; (('ux.s' bss section addresses are being overlapped
  3030                              <1> ;    when file file structure is defined in 'ux.s'))
  3031                              <1> 
  3032                              <1> %if 0
  3033                              <1> 
  3034                              <1> ; 22/11/2021
  3035                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision
  3036                              <1> 
  3037                              <1> struc file	; open files (fsp) structure
  3038                              <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  3039                              <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  3040                              <1>   .drive:  resb 1  ; logical drive (disk) number
  3041                              <1>   .flags:  resb 1  ; open mode and status
  3042                              <1>   .count:  resb 1  ; number of processes that have file open
  3043                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  3044                              <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  3045                              <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  3046                              <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  3047                              <1>  .size:  ; = 16		
  3048                              <1> endstruc
  3049                              <1> 
  3050                              <1> %endif
  3051                              <1> 
  3052                              <1> ; 01/01/2022
  3053                              <1> ; 22/11/2021
  3054                              <1> ;fp.size equ file.size
  3055                              <1> 
  3056                              <1> ; 02/01/2022
  3057 00007144 <res 320h>          <1> fsp:	resb nfiles*16 ; (NFILES*fp.size)
  3058                              <1> ; 01/01/2022
  3059                              <1> ; 22/11/2021 (16/05/2021)
  3060                              <1> ;fsp:	resb NFILES*16 ; (NFILES*fp.size)
  3061                              <1> ; 15/04/2015
  3062                              <1> ;fsp:	resb nfiles*10 ; 11/05/2015 (8 -> 10)
  3063                              <1> 
  3064 00007464 <res 20h>           <1> bufp:	resd (nbuf+2) ; will be initialized 
  3065 00007484 ????????            <1> ii:	resd 1 ; 22/11/2021 ; 32 bit inode number (high word is 0)
  3066                              <1> ; 22/11/2021
  3067 00007488 ??                  <1> idev:	resb 1 ; logical drive number of current inode, [ii]
  3068 00007489 ??                  <1> cdev:	resb 1 ; current logical drive number for current user
  3069                              <1> 
  3070                              <1> ; 18/05/2015
  3071                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  3072                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  3073                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  3074                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  3075                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  3076                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  3077                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  3078                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  3079                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  3080                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  3081                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  3082 0000748A ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  3083                              <1> 	        ; as above, for physical drives numbers in following table
  3084 0000748B ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  3085                              <1> ; 15/04/2015
  3086 0000748C ??                  <1> active:	 resb 1 
  3087 0000748D ??                  <1> 	 resb 1 ; 09/06/2015
  3088 0000748E ????                <1> mpid:	 resw 1
  3089                              <1> ; 22/11/2021 (32 bit inode numbers)
  3090 00007490 ????????            <1> rootdir: resd 1
  3091 00007494 ????????            <1> mnti:	 resd 1
  3092                              <1> 
  3093                              <1> ; 14/02/2014
  3094                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  3095                              <1> ;		      Single level run queue
  3096                              <1> ;		      (in order to solve sleep/wakeup lock)
  3097 00007498 ????                <1> runq:	resw 1
  3098 0000749A ??                  <1> imod:	resb 1
  3099 0000749B ??                  <1> imodx:	resb 1 ; 09/01/2022 - Retro UNIX 386 v1.2
  3100 0000749C ??                  <1> smod:	resb 1
  3101 0000749D ??                  <1> mmod:	resb 1
  3102                              <1> ;	resb 1 ; 09/01/2022 
  3103 0000749E ??                  <1> sysflg:	resb 1
  3104                              <1> 
  3105 0000749F ??                  <1> alignb 4
  3106                              <1> 
  3107                              <1> user:
  3108                              <1> 	; 01/01/2022
  3109                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3110                              <1> 	; 24/10/2021
  3111                              <1> 	; 18/10/2021
  3112                              <1> 	; 10/06/2021
  3113                              <1> 	; 30/05/2021
  3114                              <1> 	; 29/05/2021
  3115                              <1> 	; 21/05/2021
  3116                              <1> 	; 20/05/2021
  3117                              <1> 	; 16/05/2021
  3118                              <1> 	; 01/05/2021
  3119                              <1> 	; 27/03/2021
  3120                              <1> 	; 17/04/2020, 28/04/2020
  3121                              <1> 	; 25/03/2020, 28/03/2020
  3122                              <1> 	; 20/03/2020, 22/03/2020, 23/03/2020
  3123                              <1> 	; 05/03/2020, 08/03/2020, 14/03/2020
  3124                              <1> 	; 07/02/2020 - Retro UNIX 386 v2
  3125                              <1> 	;
  3126                              <1> 	; 27/02/2017 - TRDOS 386
  3127                              <1> 	; 13/01/2017 - TRDOS 386
  3128                              <1> 	; 10/01/2017 - TRDOS 386
  3129                              <1> 	; 19/12/2016 - TRDOS 386	
  3130                              <1> 	; 21/05/2016 - TRDOS 386 (TRDOS v2.0) 
  3131                              <1> 	; 	       [u.pri] usage method modification
  3132                              <1> 	;
  3133                              <1> 	; 04/12/2015 - Retro UNIX 386 v1.1 (14 byte file/directory names)
  3134                              <1> 	; 18/10/2015
  3135                              <1> 	; 12/10/2015
  3136                              <1> 	; 21/09/2015
  3137                              <1> 	; 24/07/2015
  3138                              <1> 	; 16/06/2015
  3139                              <1> 	; 09/06/2015
  3140                              <1> 	; 11/05/2015
  3141                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  3142                              <1> 	; 10/10/2013
  3143                              <1> 	; 11/03/2013. 
  3144                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  3145                              <1> 	;u.
  3146                              <1> 
  3147 000074A0 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  3148 000074A4 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  3149 000074A8 ????????            <1> 	u.r0:	  resd 1 ; eax
  3150 000074AC ????                <1> 	u.cdir:	  resw 1
  3151 000074AE ????                <1> 		  resw 1 ; 28/03/2020 - reserved for 32 bit inode number
  3152                              <1> 	;u.cdrv:  resw 1 ; 17/04/2020 (dword alignment) 
  3153 000074B0 ??                  <1> 	u.cdrv:   resb 1 ; 01/05/2021
  3154 000074B1 ??                  <1> 		  resb 1 ; 01/05/2021 (dword alignment)
  3155 000074B2 <res Ah>            <1> 	u.fp:	  resb 10 ; Retro UNIX 386 v1
  3156                              <1> 	;u.fp:	  resb OPENFILES ; Retro UNIX 386 v2 ; 28/03/2020 
  3157                              <1> 	u.fsp:	  ; 16/05/2021
  3158 000074BC ????????            <1> 	u.fofp:	  resd 1 ; 16/05/2021 (pointer to fsp entry)
  3159 000074C0 ????????            <1> 	u.dirp:	  resd 1
  3160 000074C4 ????????            <1> 	u.namep:  resd 1
  3161 000074C8 ????????            <1> 	u.off:	  resd 1
  3162                              <1> 	;	  resd 1 ; 08/03/2020 - Retro UNIX 386 v2 - 64 bit fptr
  3163 000074CC ????????            <1> 	u.base:	  resd 1
  3164 000074D0 ????????            <1> 	u.count:  resd 1
  3165 000074D4 ????????            <1> 	u.nread:  resd 1
  3166 000074D8 ????????            <1> 	u.break:  resd 1 ; break
  3167                              <1> 	; 16/05/2021 (Retro UNIX 386 v2)
  3168 000074DC ??                  <1> 	u.mode:   resb 1 ; 16/05/2021 (sysread, syswrite, 'rdwr' file mode)
  3169                              <1> 	; 10/01/2017 (TRDOS 386, relocation and dword alignment)
  3170                              <1> 	; tty number (rtty, rcvt, wtty)
  3171 000074DD ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  3172 000074DE ????                <1> 	u.ttyp:	  resw 1 
  3173 000074E0 <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  3174                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  3175 000074F0 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  3176 000074F1 ??                  <1> 		  resb 1 ; 17/04/2020
  3177 000074F2 ??                  <1> 	u.pri:	  resb 1 ; Modification: 21/05/2016 (priority levels: 0, 1, 2)
  3178 000074F3 ??                  <1> 		  resb 1 ; 17/04/2020
  3179                              <1> 	; 10/06/2021
  3180                              <1> 	;u.signal: resw 1 ; 21/05/2021 - Retro UNIX 386 v2
  3181                              <1> 	;	  resw 1 ; reserved ; 21/05/2021	
  3182 000074F4 ????                <1> 	u.intr:	  resw 1
  3183 000074F6 ????                <1> 	u.quit:	  resw 1
  3184                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  3185                              <1> 	;u.ilgins: resw 1 ; 10/01/2017
  3186                              <1> 	;u.cdrv:  resw 1 ; cdev ; 17/04/2020 (moved to up)
  3187                              <1> 	;u.uid:	  resb 1 ; uid
  3188                              <1> 	;u.ruid:  resb 1
  3189 000074F8 ??                  <1> 	u.bsys:	  resb 1
  3190 000074F9 ??                  <1> 	u.uno:	  resb 1
  3191 000074FA ????                <1>         u.uid:	  resw 1 ; uid	; 27/03/2021 - Retro UNIX 386 v2
  3192 000074FC ????                <1> 	u.ruid:	  resw 1	; 16 bit uid
  3193 000074FE ??                  <1> 	u.gid:	  resb 1 ; gid 	; 27/03/2021 - Retro UNIX 386 v2
  3194 000074FF ??                  <1> 	u.rgid:	  resb 1
  3195                              <1> 	; 20/05/2021 - Retro UNIX 386 v2
  3196 00007500 ????????            <1> 	u.procp:  resd 1 ; /* pointer to proc structure */		
  3197 00007504 ????????            <1> 	u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  3198 00007508 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  3199 0000750C ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  3200 00007510 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  3201                              <1> 		; 24/10/2021 (32 bit value for Retro UNIX 386 v2)
  3202 00007514 ????????            <1> 	u.pcount: resd 1 ; 20/05/2015 (byte -transfer- count for page)
  3203                              <1> 	;u.pncount: resw 1 
  3204                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  3205                              <1> 	;u.pnbase:  resd 1 
  3206                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  3207 00007518 ????                <1> 	u.rsvd:	  resw 1 ; 04/12/2021 (dword alignment)
  3208                              <1> 			 ; 09/06/2015
  3209 0000751A ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign
  3210                              <1> 		; 08/03/2020 (block device read/write flag for 'sioreg')		
  3211 0000751B ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  3212                              <1> 			 ; 24/07/2015 - 24/06/2015
  3213                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  3214                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  3215                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  3216                              <1>  			 ; 24/06/2015	  	
  3217                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  3218                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  3219                              <1> 	; last error number
  3220 0000751C ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  3221                              <1> 			; Retro UNIX 8086/386 v1 feature only!
  3222                              <1> 			; 21/09/2015 (debugging - page fault analyze)
  3223 00007520 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  3224                              <1> 		; 29/05/2021 - Retro UNIX 386 v2, 2021 (sleep, psig)
  3225                              <1> ;	u.signal: resd 1 ; unix signal recognition (enabling, accepting) bits	
  3226                              <1> ;	u.srb:	  resb 1 ; signal handling/responding method
  3227                              <1> ;	u.snum:	  resb 1 ; signal number (last signal number)
  3228                              <1> ;	u.exit:	  resb 1 ; exit code ; 30/05/2021 - Retro UNIX 386 v2
  3229                              <1> ;	u.s_lock: resb 1 ; signal handling (phase) lock	
  3230                              <1> ;	u.s_addr: resd 1 ; Signal Response Byte or signal handler (callback) address
  3231                              <1> ;	u.s_time: resd 1 ; signal time in unix epoch format		
  3232                              <1> 		; 19/12/2016 (TRDOS 386)	
  3233                              <1> ;	u.tcb:	  resd 1 ; Timer callback address/flag which will be used by timer int
  3234                              <1> 		; 13/01/2017 (TRDOS 386)
  3235                              <1> ;	u.t_lock: resb 1 ; Timer interrupt (callback) lock (unlocked by 'sysrele')
  3236                              <1> ;	u.t_mode: resb 1 ; running mode during timer interrupt (0= system, 0FFh= user)
  3237                              <1> 		; 26/02/2017 (TRDOS 386)
  3238                              <1> ;	u.irqc:	  resb 1  ; Count of IRQ callback services (IRQs in use)
  3239                              <1> 		; 28/02/2017 (TRDOS 386) 
  3240                              <1> ;	u.irqwait: resb 1 ; IRQ waiting for callback service flag (IRQ number, If > 0)
  3241                              <1> ;	u.r_lock:  resb 1 ; 'IRQ callback service is in progress' flag (IRQ lock)
  3242                              <1> ;	u.r_mode:  resb 1 ; running mode during hardware interrupt
  3243                              <1> 		; 07/02/2020 - Retro UNIX 386 v2
  3244                              <1> ;	u.redir:  resb 1 ; device func redirection permitted by user (if u.redir > 0)
  3245                              <1> 		; 26/02/2020 - Retro UNIX 386 v2
  3246                              <1> ;	u.rwm:	  resb 1  ; read & write mode for devices/drives, 0 = direct, 1 = fs r/w 
  3247                              <1> 		; 24/02/2020 - Retro UNIX 386 v2
  3248                              <1> 		; 24/10/2021 (32 bit value)
  3249                              <1> ;	u.scount: resd 1 ; sub byte count ; 22/03/2020 
  3250                              <1> 		; 07/03/2020 - Retro UNIX 386 v2
  3251                              <1> ;	u.bps:	  resw 1 ; u.bps = bytes per sector, for readi and writei
  3252                              <1> ;		  resw 1 ; 24/10/2021 (32 bit value for using with 32 bit registers)	
  3253                              <1> 		; 23/03/2020 - Retro UNIX 386 v2
  3254                              <1> ;	u.timeout: resw 1 ; timeout setting (seconds) -for 'sleep'-
  3255                              <1> 		; 28/04/2020 - Retro UNIX 386 v2
  3256                              <1> ;	u.lock:	  resb 1 ; Device lock flag (bit 0 is for device/disk read/write)
  3257                              <1> 		; 24/04/2020
  3258                              <1> 		; 17/04/2020 - Retro UNIX 386 v2
  3259                              <1> ;	u.ifs:	  resb 1 ; (current) installable file system driver index number
  3260                              <1> 		; 25/03/2020
  3261                              <1> 		; 20/03/2020
  3262                              <1> 	;u.lcount: resd 1 ; last byte count for 'writei' (for restoring write count)	
  3263                              <1> 
  3264                              <1> 		; 08/03/2020 - Retro UNIX 386 v2 ('sioreg, 'readi')
  3265                              <1> 	;u.limit: resd 1  ; disk/file size limit for block device read/write ('sioreg')			
  3266                              <1> 	;	  resd 1  ; 08/03/2020 - 64 bit limit (disk size in bytes)
  3267                              <1> 	;	; 26/02/2020 - Retro UNIX 386 v2
  3268                              <1> 	;u.sector: resd 1  ; current sector (for readi and writei, device r/w)  		
  3269                              <1> 	;u.buffer: resd 1  ; current buffer (for readi and writei, device r/w) 
  3270                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3271                              <1> 	;u.devmm: resw 1 ; device major (hb) and minor (lb) numbers
  3272                              <1> 	;u.zero:  resw 1 ; 14/03/2020 - Must be ZERO for current version
  3273                              <1> 		; 22/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3274                              <1> ;	u.device: resd 1 ; (blk, chr) device description table (entry) address 	
  3275                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3276                              <1> ;	u.function: resd 1 ; device function (read, write)
  3277                              <1> 		; 22/03/2020 - Retro UNIX 386 v2, 2020 (readi, writei)
  3278                              <1> ;	u.buffer: resd 1  ; for saving buffer header address for 'poke'
  3279                              <1> ;	u.inode:  resw 1  ; for saving inode number of current (device) inode
  3280                              <1> ;		  resw 1  ; 18/10/2021 Retro UNIX 386 v2 - 32 bit inode number			
  3281                              <1> ;	u.idev:	  resb 1  ; for saving logical drv number of current (dev) inode
  3282                              <1> 		; 04/12/2021
  3283                              <1> ;	u.rsvd2:  resw 1  ; (for dword alignment)	
  3284                              <1> 		; 27/02/2017 (TRDOS 386) 
  3285                              <1> ;; 31/12/2021 - temporary !
  3286                              <1> ;	u.fpsave: resb 1  ; TRDOS 386, 'save/restore FPU registers' flag
  3287                              <1> alignb 4
  3288                              <1> 	; !! wrong sizing in TRDOS 386 v2.0.4 (in 'ubss.s', 28/02/2017) !! 
  3289                              <1> 	;u.fpregs: resb 94 ; 94 byte area for saving and restoring FPU registers
  3290                              <1> 	; 30/05/2021 - Retro UNIX 386 v2
  3291                              <1> ;	u.fpregs: resb 108 ; 108 byte area for saving and restoring FPU registers	
  3292                              <1> alignb 4
  3293                              <1> 
  3294                              <1> U_SIZE	equ $ - user
  3295                              <1> 
  3296                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  3297 00007524 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3298 00007528 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3299 0000752C ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  3300                              <1> ;ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec'
  3301                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'ncount')
  3302 00007530 ????????            <1> ncount: resd 1	; remain byte count in page for 'namei' & 'sysexec'
  3303                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  3304                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'argc')
  3305 00007534 ????????            <1> argc:	resd 1	; argument count for 'sysexec'
  3306 00007538 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3307                              <1> 
  3308                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3309                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3310 0000753C ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3311 0000753D ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3312 0000753E ??                  <1> mget_rw: resb 1 ; 22/11/2021 
  3313 0000753F ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3314                              <1> 
  3315                              <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility
  3316                              <1> level:	resd 0  ; level, level+1, level+2, level+3  ; for 'mget' procedure
  3317                              <1> 
  3318                              <1> ; (02/01/2022)
  3319                              <1> ; 27/11/2021
  3320                              <1> ; these are will be used for disk block allocation ('alloc' proc)
  3321                              <1> free_map_offset: 
  3322 00007540 ????????            <1> 		resd 1
  3323 00007544 ????????            <1> free_map_index:	resd 1
  3324                              <1> free_map_sector:
  3325 00007548 ????????            <1> 		resd 1
  3326                              <1> ;free_map_buffer:
  3327                              <1> ;		resd 1
  3328                              <1> 
  3329                              <1> ; 12/01/2022
  3330                              <1> ; 27/11/2021 - temporary !
  3331                              <1> ;s.time:	resd 1
  3332                              <1> 
  3333                              <1> ;alignb 4
  3334                              <1> 
  3335                              <1> ; (02/01/2022)
  3336                              <1> ; 22/08/2015
  3337                              <1> ;buffer: resb nbuf * 520
  3338                              <1> 
  3339 0000754C ????????????????    <1> sb0:	resd 2
  3340                              <1> ;s:
  3341                              <1> ; (root disk) super block buffer
  3342                              <1> systm:
  3343                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatible super block
  3344                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3345                              <1> 	; 11/03/2013. 
  3346                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3347                              <1> 	;s.
  3348                              <1> 
  3349                              <1> 	;resw 1
  3350                              <1> 	;resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3351                              <1> 	;resw 1
  3352                              <1> 	;resb 32 ; 256+40 inodes ; original UNIX v1 value: 64
  3353                              <1> 	;s.time: resd 1
  3354                              <1> 	;s.syst: resd 1
  3355                              <1>         ;s.wait_: resd 1 ; wait
  3356                              <1> 	;s.idlet: resd 1
  3357                              <1> 	;s.chrgt: resd 1
  3358                              <1> 	;s.drerr: resw 1
  3359                              <1> 
  3360                              <1> 	; 27/11/2021
  3361 00007554 <res 200h>          <1> 	resb 512	
  3362                              <1> 
  3363                              <1> ;S_SIZE	equ $ - systm
  3364                              <1> 
  3365                              <1> 	;resb 512-S_SIZE ; 03/06/2015
  3366                              <1> 
  3367 00007754 ????????????????    <1> sb1:	resd 2
  3368                              <1> ; (mounted disk) super block buffer
  3369                              <1> mount:	
  3370 0000775C <res 200h>          <1> 	resb 512  ; 03/06/2015
  3371                              <1> 
  3372                              <1> ; 10/01/2022
  3373 0000795C <res 200h>          <1> dbli_buf: resb 512  ; double indir ptr buff for 'itrunc', 'tloop'
  3374 00007B5C <res 200h>          <1> trpi_buf: resb 512  ; triple indir ptr buff for 'itrunc', 'tloop'
  3375                              <1> 
  3376                              <1> ;/ ux -- unix
  3377                              <1> ;
  3378                              <1> ;systm:
  3379                              <1> ;
  3380                              <1> ;	.=.+2
  3381                              <1> ;	.=.+128.
  3382                              <1> ;	.=.+2
  3383                              <1> ;	.=.+64.
  3384                              <1> ;	s.time: .=.+4
  3385                              <1> ;	s.syst: .=.+4
  3386                              <1> ;	s.wait: .=.+4
  3387                              <1> ;	s.idlet:.=.+4
  3388                              <1> ;	s.chrgt:.=.+4
  3389                              <1> ;	s.drerr:.=.+2
  3390                              <1> ;inode:
  3391                              <1> ;	i.flgs: .=.+2
  3392                              <1> ;	i.nlks: .=.+1
  3393                              <1> ;	i.uid:  .=.+1
  3394                              <1> ;	i.size: .=.+2
  3395                              <1> ;	i.dskp: .=.+16.
  3396                              <1> ;	i.ctim: .=.+4
  3397                              <1> ;	i.mtim: .=.+4
  3398                              <1> ;	. = inode+32.
  3399                              <1> ;mount:	.=.+1024.
  3400                              <1> ;proc:
  3401                              <1> ;	p.pid:  .=.+[2*nproc]
  3402                              <1> ;	p.dska: .=.+[2*nproc]
  3403                              <1> ;	p.ppid: .=.+[2*nproc]
  3404                              <1> ;	p.break:.=.+[2*nproc]
  3405                              <1> ;	p.link: .=.+nproc
  3406                              <1> ;	p.stat: .=.+nproc
  3407                              <1> ;tty:
  3408                              <1> ;	. = .+[ntty*8.]
  3409                              <1> ;fsp:	.=.+[nfiles*8.]
  3410                              <1> ;bufp:	.=.+[nbuf*2]+6
  3411                              <1> ;sb0:	.=.+8
  3412                              <1> ;sb1:	.=.+8
  3413                              <1> ;swp:	.=.+8
  3414                              <1> ;ii:	.=.+2
  3415                              <1> ;idev:	.=.+2
  3416                              <1> ;cdev:	.=.+2
  3417                              <1> ;deverr: .=.+12.
  3418                              <1> ;active: .=.+2
  3419                              <1> ;rfap:	.=.+2
  3420                              <1> ;rkap:	.=.+2
  3421                              <1> ;tcap:	.=.+2
  3422                              <1> ;tcstate:.=.+2
  3423                              <1> ;tcerrc: .=.+2
  3424                              <1> ;mnti:	.=.+2
  3425                              <1> ;mntd:	.=.+2
  3426                              <1> ;mpid:	.=.+2
  3427                              <1> ;clockp: .=.+2
  3428                              <1> ;rootdir:.=.+2
  3429                              <1> ;toutt:	.=.+16.
  3430                              <1> ;touts: .=.+32.
  3431                              <1> ;runq:	.=.+6
  3432                              <1> ;
  3433                              <1> ;wlist:	.=.+40.
  3434                              <1> ;cc:	.=.+30.
  3435                              <1> ;cf:	.=.+31.
  3436                              <1> ;cl:	.=.+31.
  3437                              <1> ;clist:	.=.+510.
  3438                              <1> ;imod:	.=.+1
  3439                              <1> ;smod:	.=.+1
  3440                              <1> ;mmod:	.=.+1
  3441                              <1> ;uquant: .=.+1
  3442                              <1> ;sysflg: .=.+1
  3443                              <1> ;pptiflg:.=.+1
  3444                              <1> ;ttyoch: .=.+1
  3445                              <1> ; .even
  3446                              <1> ; .=.+100.; sstack:
  3447                              <1> ;buffer: .=.+[ntty*140.]
  3448                              <1> ;	.=.+[nbuf*520.]
  3449                              <1> ;
  3450                              <1> ; . = core-64.
  3451                              <1> ;user:
  3452                              <1> ;	u.sp:    .=.+2
  3453                              <1> ;	u.usp:   .=.+2
  3454                              <1> ;	u.r0:    .=.+2
  3455                              <1> ;	u.cdir:  .=.+2
  3456                              <1> ;	u.fp:    .=.+10.
  3457                              <1> ;	u.fofp:  .=.+2
  3458                              <1> ;	u.dirp:  .=.+2
  3459                              <1> ;	u.namep: .=.+2
  3460                              <1> ;	u.off:   .=.+2
  3461                              <1> ;	u.base:  .=.+2
  3462                              <1> ;	u.count: .=.+2
  3463                              <1> ;	u.nread: .=.+2
  3464                              <1> ;	u.break: .=.+2
  3465                              <1> ;	u.ttyp:  .=.+2
  3466                              <1> ;	u.dirbuf:.=.+10.
  3467                              <1> ;	u.pri:   .=.+2
  3468                              <1> ;	u.intr:  .=.+2
  3469                              <1> ;	u.quit:  .=.+2
  3470                              <1> ;	u.emt:   .=.+2
  3471                              <1> ;	u.ilgins:.=.+2
  3472                              <1> ;	u.cdev:  .=.+2
  3473                              <1> ;	u.uid:   .=.+1
  3474                              <1> ;	u.ruid:  .=.+1
  3475                              <1> ;	u.bsys:  .=.+1
  3476                              <1> ;	u.uno:   .=.+1
  3477                              <1> ;. = core
  2736                                  
  2737                                  ; 27/12/2021
  2738 00007D5C <res C30h>              buffer:	resb (nbuf*520)
  2739                                  
  2740                                  bss_end:
  2741                                  
  2742                                  ; 12/12/2021
  2743                                  BSS_SIZE equ bss_end - bss_start
  2744                                  
  2745                                  ; 27/12/2013
  2746                                  _end: ; end of kernel code (and read only data, just before bss)
