     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: 10/01/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[9A68]              	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[346B]              	mov	[mem_1m_1k], cx
   175 00000017 8916[386B]              	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[9D68]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   242 0000008A 8816[9C68]          <1>         mov     [last_drv], dl  ; last hard disk number
   243 0000008E BB[2068]            <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[9E68]            <1> 	mov	si, fd0_type
   261                              <1> L3:
   262                              <1> 	; 14/01/2015
   263 0000009F 8816[9B68]          <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[9E68]          <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[9D68]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[9B68]          <1>         mov     [drv], dl
   297 000000CB 8816[9C68]          <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[9D68]          <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[9B68]          <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[9B68]          <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[9B68]          <1> 	inc	byte [drv]
   359 0000013C BB[2068]            <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[9D68]            <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[9B68]          <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[9B68]          <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[A068]          <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[9E68]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   421 00000193 81C3[EA68]          <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[EA68]          <1> 	sub	bx, drv.status
   430 000001A5 C1E302              <1> 	shl	bx, 2
   431 000001A8 81C3[CE68]          <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[A068]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   536 00000233 808F[EC68]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[EC68]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[9C68]          <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[9B68]          <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[EA68]          <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[EA68]          <1> 	sub	bx, drv.status
   736 00000289 D0E3                <1> 	shl	bl, 1
   737 0000028B 81C3[A468]          <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[A468]          <1> 	sub	bx, drv.cylinders
   742 00000297 81C3[B268]          <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[B268]          <1>         sub     bx, drv.heads
   748 000002A6 81C3[C068]          <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[C068]          <1>         sub     bx, drv.spt
   753 000002B5 D1E3                <1> 	shl	bx, 1
   754 000002B7 81C3[CE68]          <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 B99E35                  	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[C065]                  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 B913060000              	mov	ecx, BSS_SIZE/4
   314 00000328 BF[406B0000]            	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[346B0000]          	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[B06D0000]          	mov	[free_pages], ecx
   342 00000347 8B15[386B0000]          	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[B06D0000]          	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[AC6D0000]            	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[C06D0000]            	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[A86D0000]          	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[B86D0000]            	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[C06D0000]          	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[B06D0000]          	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[AC6D0000]          	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[B06D0000]          	sub	[free_pages], ecx ; 07/11/2014
   483                                  	;
   484 00000420 8B35[A86D0000]          	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[A86D0000]          	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[AC6D0000]          	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[BC6D0000]            	mov	[first_page], eax
   564 0000048A A3[B46D0000]            	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[A86D0000]                    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[00690000]            	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[CC650000]            	mov	esi, ilist
   657 000004E5 8D3D[406B0000]          	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[75090000]            	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[C6650000]        	lidt 	[idtd]
   703                                  	;
   704                                  	; TSS descriptor setup ; 24/03/2015
   705 0000053B B8[406D0000]            	mov	eax, task_state_segment
   706 00000540 66A3[BA650000]          	mov	[gdt_tss0], ax
   707 00000546 C1C010                  	rol	eax, 16
   708 00000549 A2[BC650000]            	mov	[gdt_tss1], al
   709 0000054E 8825[BF650000]          	mov	[gdt_tss2], ah
   710 00000554 66C705[A66D0000]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[AC6D0000]          	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[446D0000]          	mov	[tss.esp0], esp
   744 00000582 66C705[486D0000]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 E8380F0000              	call	set_cpos
   771                                  	;
   772                                  	; 06/11/2014
   773                                  	; Temporary Code
   774                                  	;
   775 000005A6 E855110000              	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[A0680000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   782 000005B2 668B1D[9E680000]        	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[E9690000]            	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 E8E60D0000              	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 E82A200000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   820                                  	;
   821 000005E7 09D2                    	or	edx, edx
   822 000005E9 7407                            jz      short di3
   823                                  di2:
   824 000005EB E866200000              	call   	DISK_SETUP	; Initialize Fixed Disks
   825 000005F0 72D0                            jc      short setup_error
   826                                  di3:
   827 000005F2 E8DD100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   828                                  	;
   829 000005F7 E8E55E0000              	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[D66D0000]          	mov 	ah, [ptty] ; active (current) video page
   842 0000060B E81C5C0000              	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 E8472D0000              	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[D66D0000]          	mov	bl, [ptty]	; active_page
   871 00000625 89DE                    	mov	esi, ebx
   872 00000627 66D1E6                  	shl 	si, 1
   873 0000062A 81C6[D86D0000]          	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 E8720D0000              	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[A86D0000]          	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[A46E0000]            	mov 	[u.r0], eax
   981 00000687 89E1                    	mov	ecx, esp
   982 00000689 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   983 0000068C 890D[9C6E0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   984 00000692 8925[A06E0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   985                                  	;
   986 00000698 8B0D[A86D0000]          	mov	ecx, [k_page_dir]
   987 0000069E 0F22D9                  	mov	cr3, ecx
   988                                  T3:
   989 000006A1 FB                      	sti				; INTERRUPTS BACK ON
   990 000006A2 66FF05[246E0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   991 000006A9 7507                    	JNZ	short T4		; GO TO TEST_DAY
   992 000006AB 66FF05[266E0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   993                                  T4:					; TEST_DAY
   994 000006B2 66833D[266E0000]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[246E0000]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[246E0000]            	mov	[TIMER_LH], eax
  1005                                  	;	
  1006 000006CE C605[286E0000]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[2B6E0000]            	mov	al, [MOTOR_COUNT]
  1017 000006DC FEC8                    	dec	al
  1018                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1019 000006DE A2[2B6E0000]            	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[2A6E0000]          	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                                  
  1076                                  ; 31/12/2021 - temporary !
  1077 00000717 C3                      retn
  1078                                  
  1079                                  ;timer_int:	; IRQ 0
  1080                                  	; 06/02/2015
  1081                                  	;push	eax
  1082                                  	;push	edx
  1083                                  	;push	ecx
  1084                                  	;push	ebx
  1085                                  	;push	ds
  1086                                  	;push	es
  1087                                  	;mov	eax, KDATA
  1088                                  	;mov	ds, ax
  1089                                  	;mov	es, ax
  1090 00000718 FF05[EC6D0000]          	inc	dword [tcount]
  1091 0000071E BB[72690000]            	mov	ebx, tcountstr + 4
  1092                                  	;mov	ax, [tcount]
  1093                                  	; 04/12/2021
  1094 00000723 A1[EC6D0000]            	mov	eax, [tcount]
  1095 00000728 B90A000000              	mov	ecx, 10
  1096                                  rp_divtcnt:
  1097 0000072D 31D2                    	xor	edx, edx
  1098 0000072F F7F1                    	div	ecx
  1099 00000731 80C230                  	add	dl, 30h
  1100 00000734 8813                    	mov	[ebx], dl
  1101                                  	;or	ax, ax
  1102                                  	; 04/12/2021
  1103 00000736 09C0                    	or	eax, eax
  1104 00000738 7403                    	jz	short print_lzero
  1105 0000073A 4B                      	dec	ebx
  1106 0000073B EBF0                    	jmp	short rp_divtcnt
  1107                                  print_lzero:
  1108 0000073D 81FB[6E690000]          	cmp	ebx, tcountstr
  1109 00000743 7606                    	jna	short print_tcount
  1110 00000745 4B                      	dec	ebx
  1111 00000746 C60330                   	mov	byte [ebx], 30h
  1112 00000749 EBF2                    	jmp	short print_lzero
  1113                                  print_tcount:
  1114 0000074B 56                      	push	esi
  1115 0000074C 57                      	push	edi
  1116 0000074D BE[4A690000]            	mov	esi, timer_msg ; Timer interrupt message
  1117                                  	; 07/09/2014
  1118                                  	;mov	bx, 1	; Video page 1
  1119                                  	; 04/12/2021
  1120 00000752 29DB                    	sub	ebx, ebx
  1121                                  	;inc	bl ; ebx = 1
  1122                                  	; 02/01/2022
  1123 00000754 B306                    	mov	bl, 6	; Video page 6
  1124                                  ptmsg:
  1125 00000756 AC                      	lodsb
  1126 00000757 08C0                    	or	al, al
  1127 00000759 740D                    	jz	short ptmsg_ok
  1128 0000075B 56                      	push	esi
  1129                                  	;push	bx
  1130                                  	; 04/12/2021
  1131 0000075C 53                              push	ebx
  1132 0000075D B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1133 0000075F E8580C0000              	call 	write_tty
  1134                                  	;pop	bx
  1135                                  	; 04/12/2021
  1136 00000764 5B                      	pop	ebx
  1137 00000765 5E                      	pop	esi
  1138 00000766 EBEE                    	jmp	short ptmsg
  1139                                  	;; 27/08/2014
  1140                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1141                                  	;call	printk
  1142                                  	;
  1143                                  ptmsg_ok:
  1144                                  	; 07/09/2014
  1145                                  	;xor	dx, dx		; column 0, row 0
  1146                                  	; 04/12/2021
  1147 00000768 31D2                    	xor	edx, edx
  1148 0000076A E86F0D0000              	call	set_cpos	; set cursor position to 0,0 
  1149                                  	; 23/02/2015
  1150                                  	; 25/08/2014
  1151                                  	;mov	ebx, scounter		; (seconds counter)
  1152                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1153                                  ;	dec	byte [scounter+1]
  1154                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1155                                  ;	jns	short u_timer_retn
  1156                                  	; 26/02/2015
  1157                                  ;	call	rtc_p
  1158                                  ;	mov	ebx, scounter		; (seconds counter)
  1159                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1160                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1161                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1162                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1163                                  ;	mov	byte [ebx], 5
  1164                                  ;	inc	byte [ebx+1] ; 19
  1165                                  ;;timer_eoi:
  1166                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1167                                  ;;	out	20h, al	; 8259 PORT
  1168                                  	;
  1169                                  ;u_timer_retn:  ; 06/02/2015
  1170 0000076F 5F                      	pop	edi
  1171 00000770 5E                      	pop	esi
  1172                                  	;pop	es
  1173                                  	;pop	ds
  1174                                  	;pop	ebx
  1175                                  	;pop	ecx
  1176                                  	;pop	edx
  1177                                  	;pop	eax
  1178                                  	;iret
  1179 00000771 C3                      	retn	; 06/02/2015
  1180                                  
  1181                                  	; 28/08/2014
  1182                                  irq0:
  1183 00000772 6A00                            push 	dword 0
  1184 00000774 EB48                    	jmp	short which_irq
  1185                                  irq1:
  1186 00000776 6A01                            push 	dword 1
  1187 00000778 EB44                    	jmp	short which_irq
  1188                                  irq2:
  1189 0000077A 6A02                            push 	dword 2
  1190 0000077C EB40                    	jmp	short which_irq
  1191                                  irq3:
  1192                                  	; 20/11/2015
  1193                                  	; 24/10/2015
  1194 0000077E 2EFF15[A33A0000]        	call	dword [cs:com2_irq3]
  1195 00000785 6A03                    	push 	dword 3
  1196 00000787 EB35                    	jmp	short which_irq
  1197                                  irq4:
  1198                                  	; 20/11/2015
  1199                                  	; 24/10/2015
  1200 00000789 2EFF15[9F3A0000]        	call	dword [cs:com1_irq4]
  1201 00000790 6A04                            push 	dword 4
  1202 00000792 EB2A                    	jmp	short which_irq
  1203                                  irq5:
  1204 00000794 6A05                            push 	dword 5
  1205 00000796 EB26                    	jmp	short which_irq
  1206                                  irq6:
  1207 00000798 6A06                            push 	dword 6
  1208 0000079A EB22                    	jmp	short which_irq
  1209                                  irq7:
  1210 0000079C 6A07                            push 	dword 7
  1211 0000079E EB1E                    	jmp	short which_irq
  1212                                  irq8:
  1213 000007A0 6A08                            push 	dword 8
  1214 000007A2 EB1A                    	jmp	short which_irq
  1215                                  irq9:
  1216 000007A4 6A09                            push 	dword 9
  1217 000007A6 EB16                    	jmp	short which_irq
  1218                                  irq10:
  1219 000007A8 6A0A                            push 	dword 10
  1220 000007AA EB12                    	jmp	short which_irq
  1221                                  irq11:
  1222 000007AC 6A0B                            push 	dword 11
  1223 000007AE EB0E                    	jmp	short which_irq
  1224                                  irq12:
  1225 000007B0 6A0C                            push 	dword 12
  1226 000007B2 EB0A                    	jmp	short which_irq
  1227                                  irq13:
  1228 000007B4 6A0D                            push 	dword 13
  1229 000007B6 EB06                    	jmp	short which_irq
  1230                                  irq14:
  1231 000007B8 6A0E                            push 	dword 14
  1232 000007BA EB02                    	jmp	short which_irq
  1233                                  irq15:
  1234 000007BC 6A0F                            push 	dword 15
  1235                                  	;jmp	short which_irq
  1236                                  
  1237                                  	; 19/10/2015
  1238                                  	; 29/08/2014
  1239                                  	; 21/08/2014
  1240                                  which_irq:
  1241 000007BE 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1242 000007C1 53                      	push	ebx
  1243 000007C2 56                      	push	esi
  1244 000007C3 57                      	push	edi
  1245 000007C4 1E                      	push 	ds
  1246 000007C5 06                      	push 	es
  1247                                  	;
  1248 000007C6 88C3                    	mov	bl, al
  1249                                  	;
  1250 000007C8 B810000000              	mov	eax, KDATA
  1251 000007CD 8ED8                    	mov	ds, ax
  1252 000007CF 8EC0                    	mov	es, ax
  1253                                  	; 19/10/2015
  1254 000007D1 FC                      	cld
  1255                                          ; 27/08/2014
  1256 000007D2 8105[F8680000]A000-             add     dword [scr_row], 0A0h
  1256 000007DA 0000               
  1257                                  	;
  1258 000007DC B417                    	mov	ah, 17h	; blue (1) background, 
  1259                                  			; light gray (7) forecolor
  1260 000007DE 8B3D[F8680000]                  mov     edi, [scr_row]
  1261 000007E4 B049                    	mov	al, 'I'
  1262 000007E6 66AB                    	stosw
  1263 000007E8 B052                    	mov	al, 'R'
  1264 000007EA 66AB                    	stosw
  1265 000007EC B051                    	mov	al, 'Q'
  1266 000007EE 66AB                    	stosw
  1267 000007F0 B020                    	mov	al, ' '
  1268 000007F2 66AB                    	stosw
  1269 000007F4 88D8                    	mov	al, bl
  1270 000007F6 3C0A                    	cmp	al, 10
  1271 000007F8 7208                    	jb	short iix
  1272 000007FA B031                    	mov	al, '1'
  1273 000007FC 66AB                    	stosw
  1274 000007FE 88D8                    	mov	al, bl
  1275 00000800 2C0A                    	sub	al, 10
  1276                                  iix:
  1277 00000802 0430                    	add	al, '0'
  1278 00000804 66AB                    	stosw
  1279 00000806 B020                    	mov	al, ' '
  1280 00000808 66AB                    	stosw
  1281 0000080A B021                    	mov	al, '!'
  1282 0000080C 66AB                    	stosw
  1283 0000080E B020                    	mov	al, ' '
  1284 00000810 66AB                    	stosw
  1285                                  	; 23/02/2015
  1286 00000812 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1287                                  	;jna	iiret
  1288                                  	; 04/12/2021
  1289 00000815 7604                    	jna	short iiz
  1290                                  iiy:
  1291 00000817 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1292 00000819 E6A0                    	out	0A0h, al ; the 2nd 8259
  1293                                  iiz:
  1294 0000081B E983010000              	jmp     iiret
  1295                                  	;
  1296                                  	; 22/08/2014
  1297                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1298                                  	;out	20h, al	; 8259 PORT
  1299                                  	;
  1300                                  	;pop	es
  1301                                  	;pop	ds
  1302                                  	;pop	edi
  1303                                  	;pop	esi
  1304                                  	;pop	ebx
  1305                                  	;pop 	eax
  1306                                  	;iret
  1307                                  
  1308                                  	; 02/04/2015
  1309                                  	; 25/08/2014
  1310                                  exc0:
  1311 00000820 6A00                            push 	dword 0
  1312 00000822 E990000000                      jmp     cpu_except
  1313                                  exc1:
  1314 00000827 6A01                            push 	dword 1
  1315 00000829 E989000000                      jmp     cpu_except
  1316                                  exc2:
  1317 0000082E 6A02                            push 	dword 2
  1318 00000830 E982000000                      jmp     cpu_except
  1319                                  exc3:
  1320 00000835 6A03                            push 	dword 3
  1321 00000837 EB7E                            jmp     cpu_except
  1322                                  exc4:
  1323 00000839 6A04                            push 	dword 4
  1324 0000083B EB7A                            jmp     cpu_except
  1325                                  exc5:
  1326 0000083D 6A05                            push 	dword 5
  1327 0000083F EB76                            jmp     cpu_except
  1328                                  exc6:
  1329 00000841 6A06                            push 	dword 6
  1330 00000843 EB72                            jmp     cpu_except
  1331                                  exc7:
  1332 00000845 6A07                            push 	dword 7
  1333 00000847 EB6E                            jmp     cpu_except
  1334                                  exc8:
  1335                                  	; [esp] = Error code
  1336 00000849 6A08                            push 	dword 8
  1337 0000084B EB5C                            jmp     cpu_except_en
  1338                                  exc9:
  1339 0000084D 6A09                            push 	dword 9
  1340 0000084F EB66                            jmp     cpu_except
  1341                                  exc10:
  1342                                  	; [esp] = Error code
  1343 00000851 6A0A                            push 	dword 10
  1344 00000853 EB54                            jmp     cpu_except_en
  1345                                  exc11:
  1346                                  	; [esp] = Error code
  1347 00000855 6A0B                            push 	dword 11
  1348 00000857 EB50                            jmp     cpu_except_en
  1349                                  exc12:
  1350                                  	; [esp] = Error code
  1351 00000859 6A0C                            push 	dword 12
  1352 0000085B EB4C                            jmp     cpu_except_en
  1353                                  exc13:
  1354                                  	; [esp] = Error code
  1355 0000085D 6A0D                            push 	dword 13
  1356 0000085F EB48                            jmp     cpu_except_en
  1357                                  exc14:
  1358                                  	; [esp] = Error code
  1359 00000861 6A0E                            push 	dword 14
  1360 00000863 EB44                    	jmp	short cpu_except_en
  1361                                  exc15:
  1362 00000865 6A0F                            push 	dword 15
  1363 00000867 EB4E                            jmp     cpu_except
  1364                                  exc16:
  1365 00000869 6A10                            push 	dword 16
  1366 0000086B EB4A                            jmp     cpu_except
  1367                                  exc17:
  1368                                  	; [esp] = Error code
  1369 0000086D 6A11                            push 	dword 17
  1370 0000086F EB38                    	jmp	short cpu_except_en
  1371                                  exc18:
  1372 00000871 6A12                            push 	dword 18
  1373 00000873 EB42                    	jmp	short cpu_except
  1374                                  exc19:
  1375 00000875 6A13                            push 	dword 19
  1376 00000877 EB3E                    	jmp	short cpu_except
  1377                                  exc20:
  1378 00000879 6A14                            push 	dword 20
  1379 0000087B EB3A                    	jmp	short cpu_except
  1380                                  exc21:
  1381 0000087D 6A15                            push 	dword 21
  1382 0000087F EB36                    	jmp	short cpu_except
  1383                                  exc22:
  1384 00000881 6A16                            push 	dword 22
  1385 00000883 EB32                    	jmp	short cpu_except
  1386                                  exc23:
  1387 00000885 6A17                            push 	dword 23
  1388 00000887 EB2E                    	jmp	short cpu_except
  1389                                  exc24:
  1390 00000889 6A18                            push 	dword 24
  1391 0000088B EB2A                    	jmp	short cpu_except
  1392                                  exc25:
  1393 0000088D 6A19                            push 	dword 25
  1394 0000088F EB26                    	jmp	short cpu_except
  1395                                  exc26:
  1396 00000891 6A1A                            push 	dword 26
  1397 00000893 EB22                    	jmp	short cpu_except
  1398                                  exc27:
  1399 00000895 6A1B                            push 	dword 27
  1400 00000897 EB1E                    	jmp	short cpu_except
  1401                                  exc28:
  1402 00000899 6A1C                            push 	dword 28
  1403 0000089B EB1A                    	jmp	short cpu_except
  1404                                  exc29:
  1405 0000089D 6A1D                            push 	dword 29
  1406 0000089F EB16                    	jmp	short cpu_except
  1407                                  exc30:
  1408 000008A1 6A1E                            push 	dword 30
  1409 000008A3 EB04                    	jmp	short cpu_except_en
  1410                                  exc31:
  1411 000008A5 6A1F                            push 	dword 31
  1412 000008A7 EB0E                            jmp     short cpu_except
  1413                                  
  1414                                  	; 02/01/2022 (Retro UNIX 386 v1.2)
  1415                                  	; 19/10/2015
  1416                                  	; 19/09/2015
  1417                                  	; 01/09/2015
  1418                                  	; 28/08/2015
  1419                                  	; 28/08/2014
  1420                                  cpu_except_en:
  1421 000008A9 87442404                	xchg	eax, [esp+4] ; Error code
  1422 000008AD 36A3[586E0000]          	mov	[ss:error_code], eax
  1423 000008B3 58                      	pop	eax  ; Exception number
  1424 000008B4 870424                  	xchg	eax, [esp]
  1425                                  		; eax = eax before exception
  1426                                  		; [esp] -> exception number
  1427                                  		; [esp+4] -> EIP to return
  1428                                  	; 19/10/2015
  1429                                  	; 19/09/2015
  1430                                  	; 01/09/2015
  1431                                  	; 28/08/2015
  1432                                  	; 29/08/2014
  1433                                  	; 28/08/2014
  1434                                  	; 25/08/2014
  1435                                  	; 21/08/2014
  1436                                  cpu_except:	; CPU Exceptions
  1437 000008B7 FC                      	cld
  1438 000008B8 870424                  	xchg	eax, [esp] 
  1439                                  		; eax = Exception number
  1440                                  		; [esp] = eax (before exception)
  1441 000008BB 53                      	push	ebx
  1442 000008BC 56                      	push	esi
  1443 000008BD 57                      	push	edi
  1444 000008BE 1E                      	push 	ds
  1445 000008BF 06                      	push 	es
  1446                                  	; 28/08/2015
  1447 000008C0 66BB1000                	mov	bx, KDATA
  1448 000008C4 8EDB                    	mov	ds, bx
  1449 000008C6 8EC3                    	mov	es, bx
  1450 000008C8 0F20DB                  	mov	ebx, cr3
  1451 000008CB 53                      	push	ebx ; (*) page directory
  1452                                  	; 19/10/2015
  1453 000008CC FC                      	cld
  1454                                  	; 25/03/2015
  1455 000008CD 8B1D[A86D0000]          	mov	ebx, [k_page_dir]
  1456 000008D3 0F22DB                  	mov	cr3, ebx
  1457                                  	; 28/08/2015
  1458 000008D6 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1459 000008D9 7513                    	jne	short cpu_except_nfp
  1460 000008DB E83B280000              	call	page_fault_handler
  1461 000008E0 21C0                    	and 	eax, eax
  1462                                  	;jz	iiretp ; 01/09/2015
  1463                                  	; 02/01/2022
  1464 000008E2 7505                    	jnz	short cpu_except_pf
  1465 000008E4 E9B6000000              	jmp	iiretp
  1466                                  cpu_except_pf:
  1467 000008E9 B80E000000              	mov	eax, 0Eh ; 14
  1468                                  cpu_except_nfp:
  1469                                  	; 02/04/2015
  1470 000008EE BB[1A060000]            	mov	ebx, hang
  1471 000008F3 875C241C                	xchg	ebx, [esp+28]
  1472                                  		; EIP (points to instruction which faults)
  1473                                  	  	; New EIP (hang)
  1474 000008F7 891D[5C6E0000]          	mov	[FaultOffset], ebx
  1475 000008FD C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1476 00000905 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1477                                  	;
  1478 0000090D 88C4                    	mov	ah, al
  1479 0000090F 240F                    	and	al, 0Fh
  1480 00000911 3C09                    	cmp	al, 9
  1481 00000913 7602                    	jna	short h1ok
  1482 00000915 0407                    	add	al, 'A'-':'
  1483                                  h1ok:
  1484 00000917 D0EC                    	shr	ah, 1
  1485 00000919 D0EC                    	shr	ah, 1
  1486 0000091B D0EC                    	shr	ah, 1
  1487 0000091D D0EC                    	shr	ah, 1
  1488 0000091F 80FC09                  	cmp	ah, 9
  1489 00000922 7603                    	jna	short h2ok
  1490 00000924 80C407                  	add	ah, 'A'-':'
  1491                                  h2ok:	
  1492 00000927 86E0                    	xchg 	ah, al	
  1493 00000929 66053030                	add	ax, '00'
  1494 0000092D 66A3[86690000]          	mov	[excnstr], ax
  1495                                  	;
  1496                                  	; 29/08/2014
  1497 00000933 A1[5C6E0000]            	mov	eax, [FaultOffset]
  1498 00000938 51                      	push	ecx
  1499 00000939 52                      	push	edx
  1500 0000093A 89E3                    	mov	ebx, esp
  1501                                  	; 28/08/2015
  1502 0000093C B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1503                                  			  ; to hexadecimal string
  1504                                  	;mov	ecx, 10	    ; divisor to convert
  1505                                  			    ; binary number to decimal string
  1506                                  b2d1:
  1507 00000941 31D2                    	xor	edx, edx
  1508 00000943 F7F1                    	div	ecx
  1509                                  	;push	dx
  1510                                  	; 02/01/2022
  1511 00000945 52                      	push	edx
  1512 00000946 39C8                    	cmp	eax, ecx
  1513 00000948 73F7                    	jnb	short b2d1
  1514 0000094A BF[91690000]            	mov	edi, EIPstr ; EIP value
  1515                                  			    ; points to instruction which faults
  1516                                  	; 28/08/2015
  1517 0000094F 89C2                    	mov	edx, eax
  1518                                  b2d2:
  1519                                  	;add	al, '0'
  1520 00000951 8A82[B8170000]          	mov	al, [edx+hexchrs]
  1521 00000957 AA                      	stosb		    ; write hexadecimal digit to its place
  1522 00000958 39E3                    	cmp	ebx, esp
  1523 0000095A 7605                    	jna	short b2d3
  1524                                  	; 02/01/2022
  1525 0000095C 58                      	pop	eax
  1526                                  	;pop	ax
  1527 0000095D 88C2                    	mov	dl, al
  1528 0000095F EBF0                    	jmp	short b2d2
  1529                                  b2d3:
  1530 00000961 B068                    	mov 	al, 'h' ; 28/08/2015
  1531 00000963 AA                      	stosb
  1532 00000964 B020                    	mov	al, 20h	    ; space
  1533 00000966 AA                      	stosb
  1534 00000967 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1535 00000969 AA                      	stosb
  1536                                  	;
  1537 0000096A 5A                      	pop	edx
  1538 0000096B 59                      	pop	ecx
  1539                                  	;
  1540 0000096C B44F                    	mov	ah, 4Fh	; red (4) background, 
  1541                                  			; white (F) forecolor
  1542 0000096E BE[76690000]            	mov	esi, exc_msg ; message offset
  1543                                  	;
  1544 00000973 EB11                    	jmp	short piemsg
  1545                                  	;
  1546                                          ;add    dword [scr_row], 0A0h
  1547                                          ;mov    edi, [scr_row]
  1548                                          ;
  1549                                  	;call 	printk
  1550                                  	;
  1551                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1552                                  	;out	20h, al	; 8259 PORT
  1553                                  	;
  1554                                  	;pop	es
  1555                                  	;pop	ds
  1556                                  	;pop	edi
  1557                                  	;pop	esi
  1558                                  	;pop 	eax
  1559                                  	;iret
  1560                                  	
  1561                                  	; 28/08/2015
  1562                                  	; 23/02/2015
  1563                                  	; 20/08/2014
  1564                                  ignore_int:
  1565 00000975 50                      	push	eax
  1566 00000976 53                      	push	ebx ; 23/02/2015
  1567 00000977 56                      	push	esi
  1568 00000978 57                      	push	edi
  1569 00000979 1E                      	push 	ds
  1570 0000097A 06                      	push 	es
  1571                                  	; 28/08/2015
  1572 0000097B 0F20D8                  	mov	eax, cr3
  1573 0000097E 50                      	push	eax ; (*) page directory
  1574                                  	;
  1575 0000097F B467                    	mov	ah, 67h	; brown (6) background, 
  1576                                  			; light gray (7) forecolor
  1577 00000981 BE[34690000]            	mov	esi, int_msg ; message offset
  1578                                  piemsg:
  1579                                          ; 27/08/2014
  1580 00000986 8105[F8680000]A000-             add     dword [scr_row], 0A0h
  1580 0000098E 0000               
  1581 00000990 8B3D[F8680000]                  mov     edi, [scr_row]
  1582                                          ;
  1583 00000996 E8B9FCFFFF              	call 	printk
  1584                                  	;
  1585                                  	; 23/02/2015
  1586 0000099B B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1587 0000099D E6A0                    	out	0A0h, al ; the 2nd 8259
  1588                                  iiretp: ; 01/09/2015
  1589                                  	; 28/08/2015
  1590 0000099F 58                      	pop	eax ; (*) page directory
  1591 000009A0 0F22D8                  	mov	cr3, eax
  1592                                  	;
  1593                                  iiret:
  1594                                  	; 22/08/2014
  1595 000009A3 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1596 000009A5 E620                    	out	20h, al	; 8259 PORT
  1597                                  	;
  1598 000009A7 07                      	pop	es
  1599 000009A8 1F                      	pop	ds
  1600 000009A9 5F                      	pop	edi
  1601 000009AA 5E                      	pop	esi
  1602 000009AB 5B                      	pop	ebx ; 29/08/2014
  1603 000009AC 58                      	pop 	eax
  1604 000009AD CF                      	iretd
  1605                                  
  1606                                  	; 26/02/2015
  1607                                  	; 07/09/2014
  1608                                  	; 25/08/2014
  1609                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1610                                  	; 22/08/2014
  1611 000009AE 50                      	push	eax
  1612 000009AF 53                      	push	ebx ; 29/08/2014
  1613 000009B0 56                      	push	esi
  1614 000009B1 57                      	push	edi
  1615 000009B2 1E                      	push 	ds
  1616 000009B3 06                      	push 	es
  1617                                  	;
  1618 000009B4 B810000000              	mov	eax, KDATA
  1619 000009B9 8ED8                    	mov	ds, ax
  1620 000009BB 8EC0                    	mov	es, ax
  1621                                  	;
  1622                                  	; 25/08/2014
  1623 000009BD E884000000              	call	rtc_p
  1624                                  	;
  1625                                  	; 22/02/2015 - dsectpm.s
  1626                                  	; [ source: http://wiki.osdev.org/RTC ]
  1627                                  	; read status register C to complete procedure
  1628                                  	;(it is needed to get a next IRQ 8) 
  1629 000009C2 B00C                    	mov	al, 0Ch ; 
  1630 000009C4 E670                    	out	70h, al ; select register C
  1631 000009C6 90                      	nop
  1632 000009C7 E471                    	in	al, 71h ; just throw away contents
  1633                                  	; 22/02/2015
  1634 000009C9 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1635 000009CB E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1636                                  	;
  1637 000009CD EBD4                    	jmp	short iiret	
  1638                                  
  1639                                  	; 22/08/2014
  1640                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1641                                  	; (INT 1Ah)
  1642                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1643                                  time_of_day:
  1644 000009CF E860010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1645 000009D4 726F                            jc      short rtc_retn 
  1646 000009D6 B000                    	mov	al, CMOS_SECONDS
  1647 000009D8 E841010000              	call	CMOS_READ
  1648 000009DD A2[1C6E0000]            	mov	[time_seconds], al 
  1649 000009E2 B002                    	mov	al, CMOS_MINUTES
  1650 000009E4 E835010000              	call	CMOS_READ
  1651 000009E9 A2[1D6E0000]            	mov	[time_minutes], al 
  1652 000009EE B004                    	mov	al, CMOS_HOURS
  1653 000009F0 E829010000              	call	CMOS_READ
  1654 000009F5 A2[1E6E0000]                    mov     [time_hours], al
  1655 000009FA B006                    	mov	al, CMOS_DAY_WEEK 
  1656 000009FC E81D010000              	call	CMOS_READ
  1657 00000A01 A2[1F6E0000]            	mov	[date_wday], al
  1658 00000A06 B007                     	mov	al, CMOS_DAY_MONTH
  1659 00000A08 E811010000              	call	CMOS_READ
  1660 00000A0D A2[206E0000]            	mov	[date_day], al
  1661 00000A12 B008                    	mov	al, CMOS_MONTH
  1662 00000A14 E805010000              	call	CMOS_READ
  1663 00000A19 A2[216E0000]            	mov	[date_month], al
  1664 00000A1E B009                    	mov	al, CMOS_YEAR
  1665 00000A20 E8F9000000              	call	CMOS_READ
  1666 00000A25 A2[226E0000]            	mov	[date_year], al
  1667 00000A2A B032                    	mov	al, CMOS_CENTURY
  1668 00000A2C E8ED000000              	call	CMOS_READ
  1669 00000A31 A2[236E0000]            	mov	[date_century], al
  1670                                  	;
  1671 00000A36 B000                    	mov	al, CMOS_SECONDS
  1672 00000A38 E8E1000000              	call 	CMOS_READ
  1673 00000A3D 3A05[1C6E0000]          	cmp	al, [time_seconds]
  1674 00000A43 758A                    	jne	short time_of_day
  1675                                  
  1676                                  rtc_retn:
  1677 00000A45 C3                      	retn
  1678                                  
  1679                                  rtc_p:
  1680                                  ; 31/12/2021 - temporary !
  1681 00000A46 C3                      retn	
  1682                                  	; 27/12/2021 (Retro UNIX 386 v1.2)
  1683                                  	; 07/09/2014
  1684                                  	; 29/08/2014
  1685                                  	; 27/08/2014
  1686                                  	; 25/08/2014
  1687                                   	; Print Real Time Clock content
  1688                                  	;
  1689                                  	;
  1690 00000A47 E883FFFFFF              	call	time_of_day
  1691 00000A4C 72F7                    	jc	short rtc_retn
  1692                                  	;
  1693 00000A4E 3A05[E8690000]          	cmp	al, [ptime_seconds]
  1694 00000A54 74EF                            je      short rtc_retn ; 29/08/2014
  1695                                  	;
  1696 00000A56 A2[E8690000]            	mov	[ptime_seconds], al
  1697                                  	;
  1698 00000A5B A0[236E0000]            	mov	al, [date_century]
  1699 00000A60 E8EA000000              	call	bcd_to_ascii
  1700 00000A65 66A3[B5690000]          	mov	[datestr+6], ax
  1701 00000A6B A0[226E0000]            	mov	al, [date_year]
  1702 00000A70 E8DA000000              	call	bcd_to_ascii
  1703 00000A75 66A3[B7690000]          	mov	[datestr+8], ax
  1704 00000A7B A0[216E0000]            	mov	al, [date_month]
  1705 00000A80 E8CA000000              	call	bcd_to_ascii
  1706 00000A85 66A3[B2690000]          	mov	[datestr+3], ax
  1707 00000A8B A0[206E0000]            	mov	al, [date_day]
  1708 00000A90 E8BA000000              	call	bcd_to_ascii
  1709 00000A95 66A3[AF690000]          	mov	[datestr], ax
  1710                                  	;
  1711 00000A9B 0FB61D[1F6E0000]        	movzx	ebx, byte [date_wday]
  1712 00000AA2 C0E302                  	shl 	bl, 2
  1713 00000AA5 81C3[C8690000]          	add	ebx, daytmp
  1714 00000AAB 8B03                    	mov	eax, [ebx]
  1715 00000AAD A3[BA690000]            	mov	[daystr], eax
  1716                                  	;
  1717 00000AB2 A0[1E6E0000]            	mov	al, [time_hours]
  1718 00000AB7 E893000000              	call	bcd_to_ascii
  1719 00000ABC 66A3[BE690000]          	mov	[timestr], ax
  1720 00000AC2 A0[1D6E0000]            	mov	al, [time_minutes]
  1721 00000AC7 E883000000              	call	bcd_to_ascii
  1722 00000ACC 66A3[C1690000]          	mov	[timestr+3], ax
  1723 00000AD2 A0[1C6E0000]            	mov	al, [time_seconds]
  1724 00000AD7 E873000000              	call	bcd_to_ascii
  1725 00000ADC 66A3[C4690000]          	mov	[timestr+6], ax
  1726                                  	;		
  1727 00000AE2 BE[9D690000]            	mov	esi, rtc_msg ; message offset
  1728                                  	; 23/02/2015
  1729 00000AE7 52                      	push	edx
  1730 00000AE8 51                      	push	ecx
  1731                                  	; 07/09/2014
  1732                                  	;mov	bx, 2	; Video page 2
  1733                                  	; 27/12/2021
  1734 00000AE9 29DB                    	sub	ebx, ebx
  1735 00000AEB B302                    	mov	bl, 2
  1736                                  prtmsg:
  1737 00000AED AC                      	lodsb
  1738 00000AEE 08C0                    	or	al, al
  1739 00000AF0 740D                    	jz	short prtmsg_ok
  1740 00000AF2 56                      	push	esi
  1741                                  	;push	bx
  1742 00000AF3 53                              push	ebx ; 27/12/2021
  1743 00000AF4 B43F                    	mov	ah, 3Fh	; cyan (6) background, 
  1744                                  			; white (F) forecolor
  1745 00000AF6 E8C1080000              	call 	write_tty
  1746                                  	;pop	bx
  1747 00000AFB 5B                      	pop	ebx ; 27/12/2021
  1748 00000AFC 5E                      	pop	esi
  1749 00000AFD EBEE                    	jmp	short prtmsg
  1750                                  	;
  1751                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1752                                  	;call	printk
  1753                                  prtmsg_ok:
  1754                                  	; 07/09/2014
  1755                                  	;xor	dx, dx		; column 0, row 0
  1756                                  	; 27/12/2021
  1757 00000AFF 31D2                    	xor	edx, edx
  1758 00000B01 E8D8090000              	call	set_cpos	; set curspor position to 0,0 
  1759                                  	; 23/02/2015
  1760 00000B06 59                      	pop	ecx
  1761 00000B07 5A                      	pop	edx
  1762 00000B08 C3                      	retn
  1763                                  
  1764                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1765                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1766                                  default_irq7:
  1767                                  	; 04/12/2021
  1768                                  	;push	ax
  1769 00000B09 50                      	push	eax
  1770 00000B0A B00B                    	mov	al, 0Bh  ; In-Service register
  1771 00000B0C E620                    	out	20h, al
  1772 00000B0E EB00                            jmp short $+2
  1773 00000B10 EB00                    	jmp short $+2
  1774 00000B12 E420                    	in	al, 20h
  1775 00000B14 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1776 00000B16 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1777 00000B18 B020                            mov     al, 20h ; EOI
  1778 00000B1A E620                    	out	20h, al 
  1779                                  irq7_iret:
  1780                                  	;pop	ax
  1781                                  	; 04/12/2021
  1782 00000B1C 58                      	pop	eax
  1783 00000B1D CF                      	iretd
  1784                                  	
  1785                                  	; 04/12/2021
  1786                                  	; 22/08/2014
  1787                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1788                                  CMOS_READ:
  1789 00000B1E 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1790 00000B1F D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1791 00000B21 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1792 00000B22 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1793 00000B24 FA                      	cli		; DISABLE INTERRUPTS
  1794 00000B25 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1795 00000B27 90                      	nop		; I/O DELAY
  1796 00000B28 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1797                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1798                                  	; 04/12/2021
  1799 00000B2A 50                      	push	eax
  1800                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1801                                  		     ; ----- 10/06/85 (test4.asm)
  1802 00000B2B B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1803                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1804 00000B2D D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1805 00000B2F E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1806                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1807                                  	; 04/12/2021
  1808 00000B31 58                      	pop	eax
  1809 00000B32 9D                      	popf	
  1810 00000B33 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1811                                  
  1812                                  	; 22/08/2014
  1813                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1814                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1815 00000B34 51                      	push	ecx
  1816 00000B35 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1817                                  		; mov cx, 800	
  1818                                  UPD_10:
  1819 00000B3A B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1820 00000B3C FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1821 00000B3D E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1822 00000B42 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1823 00000B44 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1824 00000B46 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1825 00000B47 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1826 00000B49 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1827                                  		; xor ax, ax
  1828 00000B4B F9                      	stc				; SET CARRY FOR ERROR
  1829                                  UPD_90:
  1830 00000B4C 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1831 00000B4D FA                      	cli				; INTERRUPTS OFF DURING SET
  1832 00000B4E C3                      	retn				; RETURN WITH CY FLAG SET
  1833                                  
  1834                                  bcd_to_ascii:
  1835                                  	; 25/08/2014
  1836                                  	; INPUT ->
  1837                                  	;	al = Packed BCD number
  1838                                  	; OUTPUT ->
  1839                                  	;	ax  = ASCII word/number
  1840                                  	;
  1841                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1842                                  	;
  1843 00000B4F D410                    	db	0D4h, 10h		; Undocumented inst. AAM
  1844                                  					; AH = AL / 10h
  1845                                  					; AL = AL MOD 10h
  1846 00000B51 660D3030                	or	ax, '00'		; Make it ASCII based
  1847                                  
  1848 00000B55 86E0                            xchg	ah, al 
  1849                                  	
  1850 00000B57 C3                      	retn	
  1851                                  	
  1852                                  
  1853                                  %include 'keyboard.s' ; 07/03/2015
  1854                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1855                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1856                              <1> ; ****************************************************************************
  1857                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1858                              <1> ; Last Modification: 05/12/2021
  1859                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1860                              <1> ;
  1861                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1862                              <1> 
  1863                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  1864                              <1> ; 30/06/2015
  1865                              <1> ; 11/03/2015
  1866                              <1> ; 28/02/2015
  1867                              <1> ; 25/02/2015
  1868                              <1> ; 20/02/2015
  1869                              <1> ; 18/02/2015
  1870                              <1> ; 03/12/2014
  1871                              <1> ; 07/09/2014
  1872                              <1> ; KEYBOARD INTERRUPT HANDLER
  1873                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1874                              <1> 
  1875                              <1> ;getch:
  1876                              <1> ;	; 18/02/2015
  1877                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1878                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1879                              <1> ;	; routine, later... (multi tasking ability)
  1880                              <1> ;	; 28/02/2015
  1881                              <1> ;	sti	; enable interrupts
  1882                              <1> ;	;
  1883                              <1> ;	;push	esi
  1884                              <1> ;	;push	ebx
  1885                              <1> ;	;xor	ebx, ebx
  1886                              <1> ;	;mov	bl, [ptty]  ; active_page
  1887                              <1> ;	;mov	esi, ebx
  1888                              <1> ;	;shl 	si, 1
  1889                              <1> ;	;add	esi, ttychr
  1890                              <1> ;getch_1:
  1891                              <1> ;	;mov	ax, [esi]
  1892                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1893                              <1> ;	and	ax, ax
  1894                              <1> ;	jz	short getch_2
  1895                              <1> ;	mov	word [ttychr], 0
  1896                              <1> ;	;mov	word [esi], 0
  1897                              <1> ;	;pop	ebx
  1898                              <1> ;	;pop	esi
  1899                              <1> ;	retn
  1900                              <1> ;getch_2:
  1901                              <1> ;	hlt	; not proper for multi tasking!
  1902                              <1> ;		; (temporary halt for now)
  1903                              <1> ;		; 'sleep' on tty 
  1904                              <1> ;		; will (must) be located here		
  1905                              <1> ;	nop
  1906                              <1> ;	jmp	short getch_1
  1907                              <1> 
  1908                              <1> keyb_int:
  1909                              <1> 	; 30/06/2015
  1910                              <1> 	; 25/02/2015
  1911                              <1> 	; 20/02/2015
  1912                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1913                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1914                              <1> 	; 30/06/2014
  1915                              <1> 	; 10/05/2013	
  1916                              <1>       	; Retro Unix 8086 v1 feature only!
  1917                              <1> 	; 03/03/2014
  1918                              <1> 	
  1919 00000B58 1E                  <1> 	push	ds
  1920 00000B59 53                  <1> 	push	ebx
  1921 00000B5A 50                  <1> 	push	eax
  1922                              <1> 	;
  1923 00000B5B 66B81000            <1> 	mov	ax, KDATA
  1924 00000B5F 8ED8                <1> 	mov	ds, ax
  1925                              <1> 	;
  1926 00000B61 9C                  <1> 	pushfd
  1927 00000B62 0E                  <1> 	push	cs
  1928 00000B63 E812020000          <1> 	call	kb_int  ; int_09h
  1929                              <1> 	;
  1930 00000B68 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1931                              <1> 	;call	getc
  1932 00000B6A E856000000          <1> 	call	int_16h ; 30/06/2015
  1933 00000B6F 7450                <1> 	jz	short keyb_int4
  1934                              <1> 	;
  1935 00000B71 B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1936                              <1> 	;call	getc
  1937 00000B73 E84D000000          <1> 	call	int_16h ; 30/06/2015
  1938                              <1> 	;
  1939                              <1> 	; 20/02/2015
  1940 00000B78 0FB61D[D66D0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1941                              <1> 	;
  1942 00000B7F 20C0                <1> 	and 	al, al
  1943 00000B81 751E                <1> 	jnz	short keyb_int1
  1944                              <1> 	;
  1945 00000B83 80FC68              <1> 	cmp	ah, 68h	; ALT + F1 key
  1946 00000B86 7219                <1> 	jb	short keyb_int1
  1947 00000B88 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1948 00000B8B 7714                <1> 	ja	short keyb_int1
  1949                              <1> 	;
  1950 00000B8D 88D8                <1> 	mov	al, bl
  1951 00000B8F 0468                <1> 	add	al, 68h
  1952 00000B91 38E0                <1> 	cmp	al, ah
  1953 00000B93 7409                <1> 	je	short keyb_int0
  1954 00000B95 88E0                <1> 	mov	al, ah
  1955 00000B97 2C68                <1> 	sub	al, 68h
  1956 00000B99 E8FB0A0000          <1> 	call	tty_sw
  1957                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1958                              <1> keyb_int0: ; 30/06/2015
  1959 00000B9E 6631C0              <1> 	xor	ax, ax
  1960                              <1> keyb_int1:
  1961 00000BA1 D0E3                <1> 	shl	bl, 1
  1962 00000BA3 81C3[D86D0000]      <1> 	add	ebx, ttychr
  1963                              <1> 	;
  1964 00000BA9 6609C0              <1> 	or	ax, ax
  1965 00000BAC 7406                <1> 	jz	short keyb_int2
  1966                              <1> 	;
  1967 00000BAE 66833B00            <1> 	cmp 	word [ebx], 0
  1968 00000BB2 7703                <1>         ja      short keyb_int3 
  1969                              <1> keyb_int2:
  1970 00000BB4 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1971                              <1> 			   ; and scan code of the character
  1972                              <1> 			   ; for current tty (or last tty
  1973                              <1> 			   ; just before tty switch).
  1974                              <1> keyb_int3:
  1975 00000BB7 A0[D66D0000]        <1>         mov     al, [ptty]
  1976 00000BBC E88D420000          <1> 	call	wakeup
  1977                              <1> 	;
  1978                              <1> keyb_int4:
  1979 00000BC1 58                  <1> 	pop	eax
  1980 00000BC2 5B                  <1> 	pop	ebx
  1981 00000BC3 1F                  <1> 	pop	ds
  1982 00000BC4 CF                  <1> 	iret
  1983                              <1> 
  1984                              <1> ; 18/02/2015
  1985                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1986                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1987                              <1> ; scancode and ascii code of the character 
  1988                              <1> ; in the tty input (ttychr) buffer. 
  1989                              <1> ; Test procedures must call 'getch' for tty input
  1990                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1991                              <1> ; due to infinite (key press) waiting loop.
  1992                              <1> ; 
  1993                              <1> ; 03/12/2014
  1994                              <1> ; 26/08/2014
  1995                              <1> ; KEYBOARD I/O
  1996                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1997                              <1> 
  1998                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1999                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2000                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2001                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2002                              <1> 
  2003                              <1> int_16h: ; 30/06/2015
  2004                              <1> ;getc:
  2005 00000BC5 9C                  <1> 	pushfd	; 28/08/2014
  2006 00000BC6 0E                  <1> 	push 	cs
  2007 00000BC7 E826000000          <1> 	call 	getc_int
  2008 00000BCC C3                  <1> 	retn
  2009                              <1> 
  2010                              <1> ; 05/12/2021
  2011                              <1> 
  2012                              <1> 	;-----	SHIFT STATUS
  2013                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2014 00000BCD 8A25[D4670000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2015 00000BD3 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2016                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2017                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2018 00000BD6 C0E405              <1>         shl	ah, 5
  2019 00000BD9 A0[D4670000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2020 00000BDE 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2021 00000BE0 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2022 00000BE2 A0[D6670000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2023 00000BE7 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2024 00000BE9 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2025                              <1> _K3:
  2026 00000BEB A0[D3670000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2027 00000BF0 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2028                              <1> 
  2029                              <1> getc_int:
  2030                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2031                              <1> 	; 28/02/2015
  2032                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2033                              <1> 	;	      instead of pc-at bios - 1985-)
  2034                              <1> 	; 28/08/2014 (_k1d)
  2035                              <1> 	; 30/06/2014
  2036                              <1> 	; 03/03/2014
  2037                              <1> 	; 28/02/2014
  2038                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2039                              <1> 	; rombios source code (21/04/1986)
  2040                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2041                              <1> 	;
  2042                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2043                              <1> 	;
  2044                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2045                              <1> 	; KEYBOARD I/O								      :
  2046                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2047                              <1> 	; INPUT									      :
  2048                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2049                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2050                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2051                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2052                              <1> 	;-----------------------------------------------------------------------------:
  2053                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2054                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2055                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2056                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2057                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2058                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2059                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2060                              <1> 	;-----------------------------------------------------------------------------:	
  2061                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2062                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2063                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2064                              <1> 	;-----------------------------------------------------------------------------:	
  2065                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2066                              <1> 	;	      (AL) = 05H                                                      :
  2067                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2068                              <1> 	;		       							      :
  2069                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2070                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2071                              <1> 	;                     --------------------------------------------            :
  2072                              <1> 	;			00H        30.0        10H        7.5                 :
  2073                              <1> 	;			01H        26.7        11H        6.7                 :
  2074                              <1> 	;			02H        24.0        12H        6.0                 :
  2075                              <1> 	;			03H        21.8        13H        5.5                 :
  2076                              <1> 	;			04H        20.0        14H        5.0                 :
  2077                              <1> 	;			05H        18.5        15H        4.6                 :
  2078                              <1> 	;			06H        17.1        16H        4.3                 :
  2079                              <1> 	;			07H        16.0        17H        4.0                 :
  2080                              <1> 	;			08H        15.0        18H        3.7                 :
  2081                              <1> 	;			09H        13.3        19H        3.3                 :
  2082                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2083                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2084                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2085                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2086                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2087                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2088                              <1> 	;									      :
  2089                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2090                              <1> 	;		       							      :
  2091                              <1> 	;                     REGISTER     DELAY                                      :
  2092                              <1> 	;                      VALUE       VALUE                                      :
  2093                              <1> 	;                     ------------------                                      :
  2094                              <1> 	;			00H        250 ms                                     :
  2095                              <1> 	;			01H        500 ms                                     :
  2096                              <1> 	;			02H        750 ms                                     :
  2097                              <1> 	;			03H       1000 ms                                     :
  2098                              <1> 	;-----------------------------------------------------------------------------:
  2099                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2100                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2101                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2102                              <1> 	;		           (CH) = SCAN CODE                                   :
  2103                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2104                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2105                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2106                              <1> 	;-----------------------------------------------------------------------------:		
  2107                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2108                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2109                              <1> 	;-----------------------------------------------------------------------------:
  2110                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2111                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2112                              <1> 	;-----------------------------------------------------------------------------:	
  2113                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2114                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2115                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2116                              <1> 	; OUTPUT					                              :
  2117                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2118                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2119                              <1> 	;------------------------------------------------------------------------------
  2120                              <1> 	
  2121 00000BF2 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2122 00000BF3 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2123 00000BF4 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2124                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2125 00000BF5 66BB1000            <1>         mov     bx, KDATA 
  2126 00000BF9 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2127 00000BFB 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2128 00000BFD 742D                <1> 	jz	short _K1		; ASCII_READ
  2129 00000BFF FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2130 00000C01 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2131 00000C03 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2132 00000C05 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2133 00000C07 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2134 00000C09 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2135 00000C0B 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2136 00000C0E 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2137                              <1> _KIO1:	
  2138 00000C10 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2139 00000C13 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2140 00000C15 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2141 00000C17 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2142 00000C19 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2143 00000C1B 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2144                              <1> _KIO_EXIT:
  2145                              <1> 	;pop	ecx			; RECOVER REGISTER
  2146 00000C1D 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2147 00000C1E 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2148 00000C1F CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2149                              <1> 
  2150                              <1> 	;-----	ASCII CHARACTER
  2151                              <1> _K1E:	
  2152 00000C20 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2153 00000C25 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2154 00000C2A EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2155                              <1> _K1:	
  2156 00000C2C E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2157 00000C31 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2158 00000C36 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2159                              <1> _K1A:
  2160 00000C38 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2161                              <1> 
  2162                              <1> 	;-----	ASCII STATUS
  2163                              <1> _K2E:	
  2164 00000C3A E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2165 00000C3F 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2166 00000C41 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2167 00000C42 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2168 00000C47 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2169                              <1> _K2:	
  2170 00000C49 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2171 00000C4E 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2172 00000C50 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2173 00000C51 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2174 00000C56 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2175 00000C58 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2176 00000C59 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2177 00000C5E EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2178                              <1> _K2A:
  2179 00000C60 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2180                              <1> _K2B:
  2181                              <1> 	;pop	ecx			; RECOVER REGISTER
  2182 00000C61 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2183 00000C62 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2184 00000C63 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2185                              <1> 
  2186                              <1> ; 05/12/2021
  2187                              <1> ;	;-----	SHIFT STATUS
  2188                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2189                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2190                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2191                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2192                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2193                              <1> ;       shl	ah, 5
  2194                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2195                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2196                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2197                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2198                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2199                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2200                              <1> ;_K3:
  2201                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2202                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2203                              <1> 
  2204                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2205                              <1> _K300:
  2206 00000C66 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2207 00000C68 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2208 00000C6A F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2209 00000C6D 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2210 00000C6F F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2211 00000C72 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2212 00000C74 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2213 00000C76 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2214                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2215                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2216 00000C7B C0E705              <1> 	shl	bh, 5
  2217 00000C7E 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2218 00000C80 08F8                <1> 	or	al, bh			; AND DELAY
  2219 00000C82 E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2220 00000C87 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2221                              <1> 
  2222                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2223                              <1> _K500:
  2224 00000C89 56                  <1> 	push	esi			; SAVE SI (esi)
  2225 00000C8A FA                  <1> 	cli				; 
  2226 00000C8B 8B1D[E4670000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2227 00000C91 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2228 00000C93 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2229 00000C98 3B1D[E0670000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2230 00000C9E 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2231 00000CA0 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2232 00000CA3 891D[E4670000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2233 00000CA9 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2234 00000CAB EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2235                              <1> _K502:
  2236 00000CAD B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2237                              <1> _K504:
  2238 00000CAF FB                  <1> 	sti				
  2239 00000CB0 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2240 00000CB1 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2241                              <1> 
  2242                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2243                              <1> _K1S:
  2244 00000CB6 FA                  <1> 	cli	; 03/12/2014
  2245 00000CB7 8B1D[E0670000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2246 00000CBD 3B1D[E4670000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2247                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2248 00000CC3 750F                <1> 	jne	short _k1x ; 03/12/2014
  2249                              <1> 	;
  2250                              <1> 	; 03/12/2014
  2251                              <1> 	; 28/08/2014
  2252                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2253                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2254                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2255                              <1> _K1T:                                   ; ASCII READ
  2256 00000CC5 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2257 00000CC6 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2258                              <1> _K1U:	
  2259 00000CC7 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2260 00000CC8 8B1D[E0670000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2261 00000CCE 3B1D[E4670000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2262                              <1> _k1x:
  2263 00000CD4 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2264 00000CD5 9C                  <1> 	pushf				; SAVE FLAGS
  2265 00000CD6 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2266 00000CDB 8A1D[D5670000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2267 00000CE1 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2268 00000CE3 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2269 00000CE6 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2270 00000CE8 E86E060000          <1> 	call	SND_LED1
  2271 00000CED FA                  <1> 	cli				; DISABLE INTERRUPTS
  2272                              <1> _K1V:
  2273 00000CEE 9D                  <1> 	popf				; RESTORE FLAGS
  2274 00000CEF 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2275 00000CF0 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2276                              <1> 	;
  2277 00000CF2 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2278 00000CF5 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2279 00000CFA 891D[E0670000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2280 00000D00 C3                  <1> 	retn				; RETURN
  2281                              <1> 
  2282                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2283                              <1> _K2S:
  2284 00000D01 FA                  <1> 	cli				; INTERRUPTS OFF
  2285 00000D02 8B1D[E0670000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2286 00000D08 3B1D[E4670000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2287 00000D0E 668B03              <1> 	mov	ax, [ebx]
  2288 00000D11 9C                  <1> 	pushf				; SAVE FLAGS
  2289                              <1> 	;push	ax			; SAVE CODE
  2290                              <1> 	; 05/12/2021
  2291 00000D12 50                  <1> 	push	eax
  2292 00000D13 E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2293 00000D18 8A1D[D5670000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2294 00000D1E 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2295 00000D20 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2296 00000D23 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2297 00000D25 E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2298                              <1> _K2T:
  2299                              <1> 	;pop	ax			; RESTORE CODE
  2300                              <1> 	; 05/12/2021
  2301 00000D2A 58                  <1> 	pop	eax
  2302 00000D2B 9D                  <1> 	popf				; RESTORE FLAGS
  2303 00000D2C FB                  <1> 	sti				; INTERRUPTS BACK ON
  2304 00000D2D C3                  <1> 	retn				; RETURN
  2305                              <1> 
  2306                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2307                              <1> _KIO_E_XLAT:
  2308 00000D2E 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2309 00000D30 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2310 00000D32 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2311 00000D34 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2312 00000D36 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2313                              <1> _KIO_E_RET:				
  2314 00000D38 C3                  <1> 	retn				; GO BACK
  2315                              <1> 
  2316                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2317                              <1> _KIO_S_XLAT:
  2318 00000D39 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2319 00000D3C 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2320 00000D3E 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2321 00000D40 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2322 00000D42 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2323 00000D44 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2324 00000D46 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2325                              <1> _kio_ret: ; 03/12/2014
  2326 00000D48 F8                  <1> 	clc
  2327 00000D49 C3                  <1> 	retn
  2328                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2329                              <1> _KIO_S1:				
  2330 00000D4A B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2331                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2332 00000D4C C3                  <1> 	retn
  2333                              <1> _KIO_S2:		
  2334 00000D4D 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2335 00000D50 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2336 00000D52 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2337 00000D54 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2338 00000D56 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2339 00000D58 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2340 00000D5A EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2341                              <1> _KIO_S3:
  2342 00000D5C 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2343                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2344 00000D5E 75E8                <1> 	jne	short _kio_ret
  2345 00000D60 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2346 00000D62 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2347 00000D64 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2348                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2349                              <1> _KIO_USE:
  2350                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2351 00000D66 C3                  <1> 	retn				; RETURN	
  2352                              <1> _KIO_DIS:
  2353 00000D67 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2354 00000D68 C3                  <1> 	retn				; RETURN
  2355                              <1> 
  2356                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2357                              <1> _K4:    
  2358 00000D69 43                  <1> 	inc     ebx
  2359 00000D6A 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2360 00000D6B 3B1D[DC670000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2361                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2362 00000D71 7206                <1> 	jb	short _K5
  2363 00000D73 8B1D[D8670000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2364                              <1> _K5:
  2365 00000D79 C3                  <1> 	retn
  2366                              <1> 
  2367                              <1> ; 20/02/2015
  2368                              <1> ; 05/12/2014
  2369                              <1> ; 26/08/2014
  2370                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2371                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2372                              <1> ;
  2373                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2374                              <1> ; rombios source code (06/10/1985)
  2375                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2376                              <1> 
  2377                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2378                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2379                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2380                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2381                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2382                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2383                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2384                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2385                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2386                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2387                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2388                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2389                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2390                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2391                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2392                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2393                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2394                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2395                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2396                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2397                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2398                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2399                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2400                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2401                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2402                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2403                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2404                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2405                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2406                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2407                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2408                              <1> F11_M		equ	87		; F11 KEY MAKE
  2409                              <1> F12_M		equ	88		; F12 KEY MAKE
  2410                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2411                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2412                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2413                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2414                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2415                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2416                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2417                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2418                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2419                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2420                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2421                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2422                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2423                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2424                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2425                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2426                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2427                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2428                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2429                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2430                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2431                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2432                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2433                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2434                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2435                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2436                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2437                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2438                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2439                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2440                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2441                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2442                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2443                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2444                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2445                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2446                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2447                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2448                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2449                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2450                              <1> ;
  2451                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2452                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2453                              <1> INTA00		equ	020h		; 8259 PORT
  2454                              <1> 
  2455                              <1> 
  2456                              <1> kb_int:
  2457                              <1> 
  2458                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2459                              <1> ; 17/10/2015 ('ctrlbrk') 
  2460                              <1> ; 05/12/2014
  2461                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2462                              <1> 	;	      instead of pc-at bios - 1985-)
  2463                              <1> ; 26/08/2014
  2464                              <1> ;
  2465                              <1> ; 03/06/86  KEYBOARD BIOS
  2466                              <1> ;
  2467                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2468                              <1> ;										;
  2469                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2470                              <1> ;										;
  2471                              <1> ;--------------------------------------------------------------------------------
  2472                              <1> 
  2473                              <1> KB_INT_1:
  2474 00000D7A FB                  <1> 	sti				; ENABLE INTERRUPTS
  2475                              <1> 	;push	ebp
  2476 00000D7B 50                  <1> 	push	eax
  2477 00000D7C 53                  <1> 	push	ebx
  2478 00000D7D 51                  <1> 	push	ecx
  2479 00000D7E 52                  <1> 	push	edx
  2480 00000D7F 56                  <1> 	push	esi
  2481 00000D80 57                  <1> 	push	edi
  2482 00000D81 1E                  <1> 	push	ds
  2483 00000D82 06                  <1> 	push	es
  2484 00000D83 FC                  <1> 	cld				; FORWARD DIRECTION
  2485 00000D84 66B81000            <1> 	mov	ax, KDATA
  2486 00000D88 8ED8                <1> 	mov	ds, ax
  2487 00000D8A 8EC0                <1> 	mov	es, ax
  2488                              <1> 	;
  2489                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2490 00000D8C B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2491 00000D8E E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2492 00000D93 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2493 00000D94 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2494                              <1> KB_INT_01:
  2495 00000D99 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2496 00000D9B A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2497 00000D9D E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2498                              <1> 	;
  2499                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2500 00000D9F E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2501                              <1> 	;
  2502                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2503                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2504                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2505                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2506                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2507                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2508                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2509                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2510                              <1> 	;
  2511                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2512                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2513 00000DA1 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2514 00000DA2 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2515 00000DA4 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2516                              <1> 	;
  2517                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2518 00000DA6 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2519 00000DA8 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2520                              <1> 	;
  2521                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2522 00000DAA FA                  <1> 	cli				; DISABLE INTERRUPTS
  2523 00000DAB 800D[D5670000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2524 00000DB2 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2525                              <1> 	;
  2526                              <1> 	;-----	RESEND THE LAST BYTE
  2527                              <1> KB_INT_4:
  2528 00000DB7 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2529 00000DB8 800D[D5670000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2530 00000DBF E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2531                              <1> 	;
  2532                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2533                              <1> KB_INT_2:
  2534                              <1> 	;push 	ax			; SAVE DATA IN
  2535                              <1> 	; 05/12/2021
  2536 00000DC4 50                  <1> 	push	eax
  2537 00000DC5 E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2538 00000DCA 8A1D[D5670000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2539 00000DD0 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2540 00000DD2 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2541 00000DD5 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2542 00000DD7 E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2543                              <1> UP0:
  2544                              <1> 	;pop	ax			; RESTORE DATA IN
  2545                              <1> 	; 05/12/2021
  2546 00000DDC 58                  <1> 	pop	eax
  2547                              <1> ;------------------------------------------------------------------------
  2548                              <1> ;	START OF KEY PROCESSING						;
  2549                              <1> ;------------------------------------------------------------------------
  2550 00000DDD 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2551                              <1> 	;
  2552                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2553 00000DDF 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2554                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2555                              <1> 	; 05/12/2021
  2556 00000DE1 7505                <1> 	jne	short K16
  2557 00000DE3 E9ED040000          <1> 	jmp	K62
  2558                              <1> K16:	
  2559 00000DE8 8A3D[D6670000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2560                              <1> 	;
  2561                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2562 00000DEE F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2563 00000DF1 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2564 00000DF3 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2565 00000DF5 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2566 00000DF7 7507                <1> 	jne	short RST_RD_ID
  2567 00000DF9 800D[D6670000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2568                              <1> RST_RD_ID:
  2569 00000E00 8025[D6670000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2570 00000E07 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2571                              <1> 	; 05/12/2021
  2572                              <1> 	;jmp	K26
  2573                              <1> 	;
  2574                              <1> TST_ID_2:
  2575 00000E09 8025[D6670000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2576 00000E10 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2577 00000E12 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2578 00000E14 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2579 00000E16 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2580                              <1> 	; 05/12/2021
  2581                              <1> 	;jne	K26
  2582                              <1> 	;
  2583                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2584 00000E18 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2585 00000E1B 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2586 00000E1D 800D[D3670000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2587 00000E24 E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2588                              <1> KX_BIT:
  2589 00000E29 800D[D6670000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2590 00000E30 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2591                              <1> 	;
  2592                              <1> NOT_ID:
  2593 00000E35 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2594 00000E37 750E                <1> 	jne	short TEST_E1
  2595 00000E39 800D[D6670000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2596 00000E40 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2597                              <1> 	; 05/12/2021
  2598 00000E42 E9DA010000          <1> 	jmp	K26A	
  2599                              <1> TEST_E1:	
  2600 00000E47 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2601 00000E49 750C                <1> 	jne	short NOT_HC
  2602 00000E4B 800D[D6670000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2603 00000E52 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2604                              <1> 	;
  2605                              <1> NOT_HC:
  2606 00000E57 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2607 00000E59 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2608 00000E5C 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2609                              <1> 	;
  2610 00000E5E BF[BE660000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2611 00000E63 AE                  <1> 	scasb
  2612                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2613                              <1> 	; 05/12/2021
  2614 00000E64 7458                <1> 	je	short K16B
  2615 00000E66 AE                  <1> 	scasb
  2616 00000E67 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2617 00000E69 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2618                              <1> 	; 05/12/2021
  2619                              <1> 	;jmp	K26
  2620                              <1> 	;
  2621                              <1> NOT_LC_E0:
  2622 00000E6B F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2623 00000E6E 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2624 00000E70 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2625 00000E75 BF[BC660000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2626 00000E7A F2AE                <1> 	repne	scasb			; CHECK IT
  2627 00000E7C 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2628                              <1> 	; 05/12/2021
  2629                              <1> 	;je	K26A			
  2630                              <1> 	;
  2631 00000E7E 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2632 00000E80 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2633                              <1> 	; 05/12/2021
  2634                              <1> 	;jne	K26
  2635 00000E82 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2636 00000E85 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2637                              <1> 	; 05/12/2021
  2638                              <1> 	;jnz	K26
  2639                              <1>         ; 20/02/2015 
  2640 00000E87 F605[D4670000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2641 00000E8E 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2642                              <1> 	; 05/12/2021
  2643                              <1> 	;jnz	K26
  2644 00000E90 E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2645                              <1> 	;
  2646                              <1> 	;-----	TEST FOR SYSTEM KEY
  2647                              <1> T_SYS_KEY:
  2648 00000E95 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2649 00000E97 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2650                              <1> 	;
  2651 00000E99 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2652 00000E9C 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2653                              <1> 	;
  2654 00000E9E F605[D4670000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2655 00000EA5 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2656                              <1> 	;jnz	K26			
  2657                              <1> 	;
  2658 00000EA7 800D[D4670000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2659 00000EAE B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2660 00000EB0 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2661                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2662 00000EB2 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2663 00000EB4 E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2664                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2665                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2666                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2667                              <1> 	;INT	15H			; USER INTERRUPT	
  2668 00000EB9 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2669                              <1> 	;
  2670 00000EBE E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2671                              <1> 	;
  2672                              <1> K16C:
  2673 00000EC3 8025[D4670000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2674 00000ECA B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2675 00000ECC E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2676                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2677                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2678                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2679                              <1> 	;
  2680                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2681                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2682                              <1> 	;INT	15H			; USER INTERRUPT
  2683                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2684                              <1> 	;
  2685 00000ECE E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2686                              <1> 	;
  2687                              <1> 	;-----	TEST FOR SHIFT KEYS
  2688                              <1> K16A:
  2689 00000ED3 8A1D[D3670000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2690 00000ED9 BF[B8660000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2691 00000EDE B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2692 00000EE3 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2693 00000EE5 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2694                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2695                              <1> 	; 05/12/2021
  2696 00000EE7 7405                <1> 	je	short K17
  2697 00000EE9 E914010000          <1> 	jmp	K25
  2698                              <1> 	;
  2699                              <1> 	;------	SHIFT KEY FOUND
  2700                              <1> K17:
  2701 00000EEE 81EF[B9660000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2702 00000EF4 8AA7[C0660000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2703 00000EFA B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2704 00000EFC A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2705                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2706                              <1> 	; 05/12/2021
  2707 00000EFE 7405                <1> 	jz	short K17C
  2708 00000F00 E999000000          <1> 	jmp	K23
  2709                              <1> 	;
  2710                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2711                              <1> K17C:
  2712 00000F05 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2713 00000F08 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2714                              <1> 	;
  2715                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2716 00000F0A 0825[D3670000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2717 00000F10 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2718 00000F12 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2719                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2720                              <1> 	; 05/12/2021
  2721 00000F14 E901010000          <1> 	jmp	K26
  2722                              <1> K17D:
  2723 00000F19 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2724 00000F1C 740B                <1> 	jz 	short K17E		; NO, JUMP
  2725 00000F1E 0825[D6670000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2726 00000F24 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2727                              <1> K17E:
  2728 00000F29 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2729 00000F2B 0825[D4670000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2730 00000F31 E9E4000000          <1> 	jmp	K26
  2731                              <1> 	;
  2732                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2733                              <1> K18:					; SHIFT-TOGGLE
  2734 00000F36 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2735 00000F39 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2736                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2737                              <1> 	; 05/12/2021
  2738 00000F3B E9C2000000          <1> 	jmp	K25
  2739                              <1> K18A:
  2740 00000F40 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2741 00000F42 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2742 00000F44 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2743 00000F47 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2744                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2745                              <1> 	; 05/12/2021
  2746 00000F49 E9B4000000          <1> 	jmp	K25
  2747                              <1> K18B:
  2748 00000F4E F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2749 00000F51 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2750                              <1> K19:	
  2751 00000F53 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2752 00000F56 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2753 00000F58 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2754 00000F5B 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2755                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2756 00000F5D 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2757 00000F5F E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2758                              <1> K21:					; MIGHT BE NUMERIC
  2759 00000F64 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2760 00000F67 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2761                              <1> 	;
  2762                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2763 00000F69 8425[D4670000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2764                              <1> 	;jnz	K26
  2765                              <1> 	; 05/12/2021
  2766 00000F6F 7405                <1> 	jz	short K22A
  2767 00000F71 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2768                              <1> K22A:
  2769 00000F76 0825[D4670000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2770 00000F7C 3025[D3670000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2771                              <1> 	;
  2772                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2773 00000F82 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2774 00000F85 7407                <1> 	jz	short K22B		; GO IF NOT
  2775                              <1> 	;
  2776                              <1> 	; 05/12/2021
  2777                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2778 00000F87 50                  <1> 	push	eax
  2779 00000F88 E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2780                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2781 00000F8D 58                  <1> 	pop	eax
  2782                              <1> K22B:
  2783 00000F8E 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2784                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2785                              <1> 	; 05/12/2021
  2786 00000F90 7405                <1> 	je	short K22C
  2787 00000F92 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2788                              <1> K22C:
  2789 00000F97 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2790 00000F99 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2791                              <1> 	;
  2792                              <1> 	;-----	BREAK SHIFT FOUND
  2793                              <1> K23:					; BREAK-SHIFT-FOUND
  2794 00000F9E 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2795 00000FA1 F6D4                <1> 	not	ah			; INVERT MASK
  2796 00000FA3 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2797 00000FA5 2025[D3670000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2798 00000FAB 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2799 00000FAE 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2800                              <1> 	;
  2801 00000FB0 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2802 00000FB3 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2803 00000FB5 2025[D6670000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2804 00000FBB EB08                <1> 	jmp	short K23B		; CONTINUE
  2805                              <1> K23A:
  2806 00000FBD D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2807 00000FBF 2025[D4670000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2808                              <1> K23B:
  2809 00000FC5 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2810 00000FC7 A0[D6670000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2811 00000FCC D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2812 00000FCE 0A05[D4670000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2813 00000FD4 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2814 00000FD6 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2815 00000FD8 0805[D3670000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2816 00000FDE 88E0                <1> 	mov	al, ah
  2817                              <1> K23D:
  2818 00000FE0 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2819 00000FE2 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2820                              <1> 	;	
  2821                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2822 00000FE4 A0[D7670000]        <1> 	mov	al, [ALT_INPUT]
  2823 00000FE9 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2824 00000FEB 8825[D7670000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2825 00000FF1 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2826 00000FF3 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2827 00000FF5 E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2828                              <1> 	;
  2829                              <1> K24:					; BREAK-TOGGLE
  2830 00000FFA 2025[D4670000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2831 00001000 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2832                              <1> 	;
  2833                              <1> 	;-----	TEST FOR HOLD STATE
  2834                              <1> 					; AL, AH = SCAN CODE
  2835                              <1> K25:					; NO-SHIFT-FOUND
  2836 00001002 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2837 00001004 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2838 00001006 F605[D4670000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2839 0000100D 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2840 0000100F 3C45                <1> 	cmp	al, NUM_KEY
  2841 00001011 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2842 00001013 8025[D4670000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2843                              <1> 	;
  2844                              <1> K26:
  2845 0000101A 8025[D6670000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2846                              <1> K26A:					; INTERRUPT-RETURN
  2847 00001021 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2848 00001022 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2849 00001024 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2850                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2851 00001026 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2852 00001028 E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2853                              <1> K27A:
  2854 0000102D FA                  <1> 	cli				; DISABLE INTERRUPTS
  2855 0000102E 07                  <1> 	pop	es			; RESTORE REGISTERS
  2856 0000102F 1F                  <1> 	pop	ds
  2857 00001030 5F                  <1> 	pop	edi
  2858 00001031 5E                  <1> 	pop	esi
  2859 00001032 5A                  <1> 	pop	edx
  2860 00001033 59                  <1> 	pop	ecx
  2861 00001034 5B                  <1> 	pop	ebx
  2862 00001035 58                  <1> 	pop	eax
  2863                              <1> 	;pop	ebp
  2864 00001036 CF                  <1> 	iret				; RETURN
  2865                              <1> 
  2866                              <1> 	;-----	NOT IN	HOLD STATE
  2867                              <1> K28:					; NO-HOLD-STATE
  2868 00001037 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2869 00001039 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2870                              <1> 	;
  2871 0000103B F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2872 0000103E 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2873                              <1>         ; 05/12/2021
  2874                              <1> 	;jz      K38
  2875                              <1> 	;
  2876 00001040 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2877 00001043 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2878                              <1> 	; 28/02/2015
  2879 00001045 F605[D4670000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2880 0000104C 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2881                              <1> 	; 05/12/2021
  2882                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2883                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2884 0000104E E9D1000000          <1> K28A:	jmp	K38
  2885                              <1> 	;
  2886                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2887                              <1> K29:					; TEST-RESET
  2888 00001053 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2889 00001056 740B                <1> 	jz	short K31		; NO_RESET
  2890 00001058 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2891 0000105A 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2892                              <1> 	;
  2893                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2894                              <1>  	; 26/08/2014
  2895                              <1> cpu_reset:
  2896                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2897                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2898 0000105C B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2899 0000105E E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2900                              <1> khere:
  2901 00001060 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2902 00001061 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2903                              <1> 
  2904                              <1> 	;
  2905                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2906                              <1> K31:					; NO-RESET
  2907 00001063 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2908 00001065 7507                <1> 	jne	short K311		; NOT THERE
  2909 00001067 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2910 00001069 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2911                              <1> K311:
  2912 0000106E 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2913 00001070 7509                <1> 	jne	short K312		; NOT THERE
  2914 00001072 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2915 00001076 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2916                              <1> K312:
  2917 0000107B 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2918 0000107D 7471                <1>         je	short K37B              ; GO PROCESS
  2919 0000107F 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2920 00001081 746D                <1>         je	short K37B              ; GO PROCESS
  2921                              <1> 	;
  2922                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2923                              <1> K32:					; ALT-KEY-PAD
  2924 00001083 BF[94660000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2925 00001088 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2926 0000108D F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2927 0000108F 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2928 00001091 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2929                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2930                              <1> 	; 05/12/2021
  2931 00001094 751C                <1> 	jnz	short K32B
  2932 00001096 81EF[95660000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2933 0000109C A0[D7670000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2934 000010A1 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2935 000010A3 F6E4                <1> 	mul	ah
  2936 000010A5 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2937 000010A8 A2[D7670000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2938                              <1> K32A:
  2939 000010AD E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2940                              <1> K32B:
  2941                              <1> 	; 05/12/2021
  2942 000010B2 EB6A                <1> 	jmp	K37C
  2943                              <1> 	;
  2944                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2945                              <1> K33:					; NO-ALT-KEYPAD
  2946 000010B4 C605[D7670000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2947 000010BB B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2948 000010C0 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2949 000010C2 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2950                              <1> 	;
  2951                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2952                              <1> K34:					; ALT-TOP-ROW
  2953 000010C4 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2954 000010C6 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2955 000010C8 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2956 000010CA 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2957 000010CC 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2958 000010CF EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2959                              <1> 	;
  2960                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2961                              <1> K35:					; ALT-FUNCTION
  2962 000010D1 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2963 000010D3 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2964 000010D5 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2965 000010D7 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2966 000010D9 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2967 000010DC EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2968                              <1> K35A:
  2969 000010DE F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2970 000010E1 7425                <1> 	jz	short K37		; NO, JUMP
  2971 000010E3 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2972 000010E5 7510                <1>         jne     short K35B              ; NOT THERE
  2973 000010E7 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2974 000010EB E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2975                              <1> K37B:
  2976 000010F0 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2977 000010F2 E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2978                              <1> K35B:
  2979 000010F7 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2980 000010F9 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2981 000010FB 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2982 000010FD 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2983                              <1>         ; 05/12/2021
  2984                              <1> 	;jne	K26
  2985 000010FF 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2986 00001103 E99C010000          <1> 	jmp	K57			; BUFFER FILL
  2987                              <1> K37:
  2988 00001108 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2989 0000110A 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2990 0000110C 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2991                              <1>         ;ja	short K32A		; IF SO, IGNORE
  2992 0000110E 0F8706FFFFFF        <1>         ja      K26
  2993 00001114 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2994                              <1> K37A:
  2995 00001117 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2996 00001119 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2997                              <1> K37C:
  2998 0000111E 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2999 00001120 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3000 00001122 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3001                              <1> 	;
  3002                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3003                              <1> K38:					; NOT-ALT-SHIFT
  3004                              <1> 					; BL STILL HAS SHIFT FLAGS
  3005 00001124 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3006 00001127 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3007                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3008                              <1> 	; 05/12/2021
  3009 00001129 E9AB000000          <1> 	jmp	K44
  3010                              <1> 	;
  3011                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3012                              <1> 	;-----	TEST FOR BREAK
  3013                              <1> K38A:
  3014 0000112E 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3015 00001130 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3016 00001132 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3017 00001135 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3018 00001137 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3019 0000113A 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3020                              <1> K38B:
  3021 0000113C 8B1D[E0670000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3022 00001142 891D[E4670000]      <1> 	mov	[BUFFER_TAIL], ebx
  3023 00001148 C605[D2670000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3024                              <1> 	;
  3025                              <1> 	;-----	ENABLE KEYBOARD
  3026 0000114F B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3027 00001151 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3028                              <1> 	;
  3029                              <1> 	; CTRL+BREAK code here !!!
  3030                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3031                              <1> 	; 17/10/2015	
  3032 00001156 E823230000          <1> 	call	ctrlbrk ; control+break subroutine
  3033                              <1> 	;
  3034                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3035                              <1> 	; 05/12/2021
  3036 0000115B 29C0                <1> 	sub	eax, eax
  3037 0000115D E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3038                              <1> 	;
  3039                              <1> 	;-----	TEST FOR PAUSE
  3040                              <1> K39:					; NO_BREAK
  3041 00001162 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3042 00001165 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3043 00001167 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3044 00001169 7533                <1> 	jne	short K41		; NO-PAUSE
  3045                              <1> K39P:
  3046 0000116B 800D[D4670000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3047                              <1> 	;
  3048                              <1> 	;-----	ENABLE KEYBOARD
  3049 00001172 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3050 00001174 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3051                              <1> K39A:
  3052 00001179 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3053 0000117B E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3054                              <1> 	;
  3055                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3056 0000117D 803D[D0670000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3057 00001184 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3058 00001186 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3059 0000118A A0[D1670000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3060 0000118F EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3061                              <1> 	;
  3062                              <1> K40:					; PAUSE-LOOP
  3063 00001190 F605[D4670000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3064 00001197 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3065                              <1> 	;
  3066 00001199 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3067                              <1>         ;
  3068                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3069                              <1> K41:					; NO-PAUSE
  3070 0000119E 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3071 000011A0 7513                <1> 	jne	short K42		; NOT-KEY-55
  3072 000011A2 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3073 000011A5 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3074 000011A7 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3075 000011AA 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3076                              <1> K41A:	
  3077 000011AC 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3078 000011B0 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3079                              <1> 	;
  3080                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3081                              <1> K42:					; NOT-KEY-55
  3082 000011B5 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3083 000011B7 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3084 000011B9 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3085 000011BB 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3086 000011BD F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3087 000011C0 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3088 000011C2 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3089 000011C6 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3090                              <1> K42A:
  3091                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3092 000011CB 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3093                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3094                              <1> 	;;jb	K56 ; 20/02/2015
  3095                              <1> 	;;jmp	K64 ; 20/02/2015
  3096                              <1> K42B:
  3097 000011CD BB[C8660000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3098                              <1> 	;;jmp	K64
  3099                              <1> 	;jb	K56 ;; 20/02/2015	
  3100                              <1> 	; 05/12/2021
  3101 000011D2 7267                <1> 	jb	short K45F
  3102 000011D4 E9B9000000          <1> 	jmp	K64	
  3103                              <1>         ;
  3104                              <1> 	;-----	NOT IN CONTROL SHIFT
  3105                              <1> K44:					; NOT-CTL-SHIFT
  3106 000011D9 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3107 000011DB 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3108 000011DD F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3109 000011E0 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3110 000011E2 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3111 000011E5 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3112 000011E7 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3113                              <1> K44A:
  3114 000011E9 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3115 000011EC 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3116                              <1> 	;
  3117                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3118                              <1> K44B:
  3119 000011EE B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3120 000011F0 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3121 000011F5 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3122 000011F7 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3123                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3124                              <1> 	;PUSH 	BP			; SAVE POINTER
  3125                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3126                              <1> 	;POP	BP			; RESTORE POINTER
  3127 000011F9 8025[D6670000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3128 00001200 E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3129                              <1> 	;
  3130                              <1> 	;-----	HANDLE IN-CORE KEYS
  3131                              <1> K45:					; NOT-PRINT-SCREEN
  3132 00001205 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3133 00001207 7734                <1> 	ja	short K46		; JUMP IF NOT
  3134 00001209 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3135 0000120B 7505                <1> 	jne	short K45A		; NO, JUMP
  3136 0000120D F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3137 00001210 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3138                              <1> K45A:
  3139 00001212 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3140 00001217 BF[9E660000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3141 0000121C F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3142                              <1> 		; 20/02/2015
  3143 0000121E 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3144                              <1> 	;
  3145 00001220 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3146 00001223 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3147                              <1> K45B:
  3148 00001225 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3149 00001228 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3150                              <1> 					; NO, LOWERCASE
  3151                              <1> K45C:
  3152 0000122A BB[20670000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3153 0000122F EB51                <1> 	jmp	short K56	
  3154                              <1> K45D:					; ALMOST-CAPS-STATE
  3155 00001231 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3156 00001234 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3157                              <1> K45E:
  3158 00001236 BB[78670000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3159 0000123B EB45                <1> K45F:	jmp	short K56
  3160                              <1> 	;
  3161                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3162                              <1> K46:					; NOT IN-CORE AREA
  3163 0000123D 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3164                              <1> 	;ja	short K47		; JUMP IF NOT
  3165                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3166 0000123F 7635                <1> 	jna	short K53		
  3167                              <1> 	;
  3168                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3169                              <1> K47:					; NOT F1 - F10
  3170 00001241 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3171 00001243 772D                <1> 	ja	short K52		; JUMP IF NOT
  3172                              <1> 	;
  3173                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3174                              <1> K48:
  3175 00001245 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3176 00001247 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3177 00001249 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3178 0000124B 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3179 0000124D F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3180 00001250 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3181                              <1> 	;		
  3182 00001252 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3183 00001255 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3184 00001257 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3185                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3186 0000125A 75DA                <1> 	jnz	short K45E
  3187                              <1> 	;
  3188                              <1> 	;-----	BASE CASE FOR KEYPAD
  3189                              <1> K49:					
  3190 0000125C 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3191 0000125E 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3192 00001260 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3193 00001262 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3194                              <1> K49A:
  3195 00001264 BB[20670000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3196 00001269 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3197                              <1> 	;
  3198                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3199                              <1> K50:					; ALMOST-NUM-STATE
  3200 0000126B F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3201 0000126E 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3202 00001270 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3203                              <1> 	;
  3204                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3205                              <1> K52:					; NOT A NUMPAD KEY
  3206 00001272 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3207                              <1> 	;jne	short K53		; JUMP IF NOT
  3208                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3209 00001274 74AF                <1> 	je	short K45B		
  3210                              <1> 	;
  3211                              <1> 	;-----	MUST BE F11 OR F12 
  3212                              <1> K53:					; F1 - F10 COME HERE, TOO
  3213 00001276 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3214 00001279 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3215                              <1> 		; 20/02/2015 
  3216 0000127B BB[78670000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3217 00001280 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3218                              <1> 	;
  3219                              <1> 	;-----	TRANSLATE THE CHARACTER
  3220                              <1> K56:					; TRANSLATE-CHAR
  3221 00001282 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3222 00001284 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3223 00001285 F605[D6670000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3224 0000128C 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3225 0000128E B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3226 00001290 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3227                              <1> 	;
  3228                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3229                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3230 00001292 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3231 00001294 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3232 00001295 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3233 00001297 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3234 00001299 F605[D6670000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3235 000012A0 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3236 000012A2 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3237                              <1> 	;
  3238                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3239                              <1> K57:					; BUFFER_FILL
  3240 000012A4 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3241 000012A6 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3242                              <1> 	; 05/12/2021
  3243                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3244 000012A8 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3245                              <1> 	; 05/12/2021
  3246 000012AB 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3247                              <1> 	;je	K26			; INTERRUPT_RETURN
  3248                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3249 000012AD E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3250                              <1> K61:					; NOT-CAPS-STATE
  3251 000012B2 8B1D[E4670000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3252 000012B8 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3253 000012BA E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3254 000012BF 3B1D[E0670000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3255 000012C5 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3256 000012C7 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3257 000012CA 891D[E4670000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3258 000012D0 E945FDFFFF          <1> 	jmp	K26
  3259                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3260                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3261                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3262                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3263                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3264                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3265                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3266                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3267                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3268                              <1> 	;;jmp   K27                    
  3269                              <1> 	;
  3270                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3271                              <1> K62:
  3272 000012D5 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3273 000012D7 E620                <1> 	out	INTA00, al
  3274 000012D9 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3275 000012DD B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3276 000012DF E89B010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3277 000012E4 E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3278                              <1> 
  3279                              <1> SHIP_IT:
  3280                              <1> 	;---------------------------------------------------------------------------------
  3281                              <1> 	; SHIP_IT
  3282                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3283                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3284                              <1> 	;---------------------------------------------------------------------------------
  3285                              <1> 	;
  3286                              <1> 	;push	ax			; SAVE DATA TO SEND
  3287                              <1> 	; 05/12/2021
  3288 000012E9 50                  <1> 	push	eax
  3289                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3290 000012EA FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3291                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3292 000012EB B900000100          <1> 	mov	ecx, 10000h			
  3293                              <1> S10:
  3294 000012F0 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3295 000012F2 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3296 000012F4 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3297                              <1> 
  3298                              <1> 	;pop	ax			; GET DATA TO SEND
  3299                              <1> 	; 05/12/2021
  3300 000012F6 58                  <1> 	pop	eax
  3301 000012F7 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3302 000012F9 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3303 000012FA C3                  <1> 	retn				; RETURN TO CALLER
  3304                              <1> 
  3305                              <1> SND_DATA:
  3306                              <1> 	; ---------------------------------------------------------------------------------
  3307                              <1> 	; SND_DATA
  3308                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3309                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3310                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3311                              <1> 	; ---------------------------------------------------------------------------------
  3312                              <1> 	;
  3313                              <1> 	;push	ax			; SAVE REGISTERS
  3314                              <1> 	;push	bx
  3315                              <1> 	; 05/12/2021
  3316 000012FB 50                  <1> 	push	eax
  3317 000012FC 53                  <1> 	push	ebx
  3318 000012FD 51                  <1> 	push	ecx
  3319 000012FE 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3320 00001300 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3321                              <1> SD0:
  3322 00001302 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3323 00001303 8025[D5670000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3324                              <1> 	;
  3325                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3326 0000130A B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3327                              <1> SD5:
  3328 0000130F E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3329 00001311 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3330 00001313 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3331                              <1> 	;
  3332 00001315 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3333 00001317 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3334 00001319 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3335                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3336 0000131A B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3337                              <1> SD1:
  3338 0000131F F605[D5670000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3339 00001326 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3340 00001328 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3341                              <1> SD2:
  3342 0000132A FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3343 0000132C 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3344 0000132E 800D[D5670000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3345 00001335 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3346                              <1> SD3:
  3347 00001337 F605[D5670000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3348 0000133E 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3349                              <1> SD4:	
  3350 00001340 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3351                              <1> 	;pop	bx
  3352                              <1> 	;pop	ax
  3353                              <1> 	; 05/12/2021
  3354 00001341 5B                  <1> 	pop	ebx
  3355 00001342 58                  <1> 	pop	eax
  3356 00001343 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3357                              <1> 
  3358                              <1> SND_LED:
  3359                              <1> 	; ---------------------------------------------------------------------------------
  3360                              <1> 	; SND_LED
  3361                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3362                              <1> 	;
  3363                              <1> 	;----------------------------------------------------------------------------------
  3364                              <1> 	;
  3365 00001344 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3366 00001345 F605[D5670000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3367 0000134C 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3368                              <1> 	;
  3369 0000134E 800D[D5670000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3370 00001355 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3371 00001357 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3372 00001359 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3373                              <1> SND_LED1:
  3374 0000135B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3375 0000135C F605[D5670000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3376 00001363 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3377                              <1> 	;
  3378 00001365 800D[D5670000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3379                              <1> SL0:
  3380 0000136C B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3381 0000136E E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3382 00001373 FA                  <1> 	cli
  3383 00001374 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3384 00001379 8025[D5670000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3385 00001380 0805[D5670000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3386 00001386 F605[D5670000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3387 0000138D 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3388                              <1> 	;
  3389 0000138F E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3390 00001394 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3391 00001395 F605[D5670000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3392 0000139C 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3393                              <1> SL2:
  3394 0000139E B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3395 000013A0 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3396 000013A5 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3397                              <1> SL3:
  3398 000013A6 8025[D5670000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3399                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3400 000013AD FB                  <1> 	sti				; ENABLE INTERRUPTS
  3401 000013AE C3                  <1> 	retn				; RETURN TO CALLER
  3402                              <1> 
  3403                              <1> MAKE_LED:
  3404                              <1> 	;---------------------------------------------------------------------------------
  3405                              <1> 	; MAKE_LED
  3406                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3407                              <1> 	;	THE MODE INDICATORS.
  3408                              <1> 	;---------------------------------------------------------------------------------
  3409                              <1> 	;
  3410                              <1> 	;push 	cx			; SAVE CX
  3411 000013AF A0[D3670000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3412 000013B4 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3413                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3414                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3415 000013B6 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3416 000013B9 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3417                              <1> 	;pop	cx
  3418 000013BB C3                  <1> 	retn				; RETURN TO CALLER
  3419                              <1> 
  3420                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3421                              <1> 
  3422                              <1> 
  3423                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1854                                  
  1855                                  %include 'video.s' ; 07/03/2015
  1856                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1857                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1858                              <1> ; ****************************************************************************
  1859                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1860                              <1> ; Last Modification: 05/12/2021
  1861                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1862                              <1> ;
  1863                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1864                              <1> 
  1865                              <1> ; 05/12/2021
  1866                              <1> ; 30/06/2015
  1867                              <1> ; 27/06/2015
  1868                              <1> ; 11/03/2015
  1869                              <1> ; 02/09/2014
  1870                              <1> ; 30/08/2014
  1871                              <1> ; VIDEO FUNCTIONS
  1872                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1873                              <1> 
  1874                              <1> write_tty:
  1875                              <1> 	; 13/08/2015
  1876                              <1> 	; 02/09/2014
  1877                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1878                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1879                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1880                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1881                              <1> 	;
  1882                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1883                              <1> 	;	   AL = Character to be written
  1884                              <1> 	;	   EBX = Video Page (0 to 7)
  1885                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1886                              <1> 
  1887                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1888                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1889                              <1> 
  1890                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1891                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1892                              <1> ;
  1893                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1894                              <1> ;
  1895                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1896                              <1> ;										:
  1897                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1898                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1899                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1900                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1901                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1902                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1903                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1904                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1905                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1906                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1907                              <1> ;   THE 0 COLOR IS USED.							:
  1908                              <1> ;   ENTRY --									:
  1909                              <1> ;     (AH) = CURRENT CRT MODE							:
  1910                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1911                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1912                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1913                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1914                              <1> ;   EXIT -- 									:
  1915                              <1> ;     ALL REGISTERS SAVED							:
  1916                              <1> ;--------------------------------------------------------------------------------
  1917                              <1> 
  1918 000013BC FA                  <1> 	cli
  1919                              <1> 	;
  1920                              <1> 	; READ CURSOR (04/12/2013)
  1921                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1922 000013BD 08FF                <1> 	or	bh, bh
  1923 000013BF 0F85AB000000        <1> 	jnz	beeper
  1924                              <1> 	; 01/09/2014
  1925 000013C5 803D[D0670000]03    <1> 	cmp	byte [CRT_MODE], 3
  1926 000013CC 7405                <1> 	je	short m3
  1927                              <1> 	;
  1928 000013CE E876020000          <1> 	call	set_mode
  1929                              <1> m3:
  1930 000013D3 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1931 000013D5 66D1E6              <1> 	shl	si, 1
  1932 000013D8 81C6[C66D0000]      <1> 	add	esi, cursor_posn
  1933 000013DE 668B16              <1> 	mov	dx, [esi]
  1934                              <1> 	;
  1935                              <1> 	; dx now has the current cursor position
  1936                              <1> 	;
  1937 000013E1 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1938 000013E3 764D                <1> 	jbe	short u8
  1939                              <1> 	;
  1940                              <1> 	; write the char to the screen
  1941                              <1> u0:	
  1942                              <1> 	; ah = attribute/color
  1943                              <1> 	; al = character
  1944                              <1> 	; bl = video page number (0 to 7)
  1945                              <1> 	; bh = 0
  1946                              <1> 	;
  1947 000013E5 E832020000          <1> 	call	write_c_current
  1948                              <1> 	;
  1949                              <1> 	; position the cursor for next char
  1950 000013EA FEC2                <1> 	inc	dl		; next column
  1951                              <1> 	;cmp	dl, [CRT_COLS]
  1952 000013EC 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1953 000013EF 0F85E9000000        <1>         jne     set_cpos
  1954 000013F5 B200                <1> 	mov	dl, 0		; column = 0
  1955                              <1> u10:				; (line feed found)
  1956 000013F7 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1957 000013FA 722F                <1> 	jb 	short u6
  1958                              <1> 	;
  1959                              <1> 	; scroll required
  1960                              <1> u1:	
  1961                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1962 000013FC E8DD000000          <1> 	call	set_cpos
  1963                              <1> 	;
  1964                              <1> 	; determine value to fill with during scroll
  1965                              <1> u2:
  1966                              <1> 	; READ_AC_CURRENT		:
  1967                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1968                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1969                              <1> 	;
  1970                              <1> 	; INPUT				
  1971                              <1> 	;	(AH) = CURRENT CRT MODE
  1972                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1973                              <1> 	;	(DS) = DATA SEGMENT
  1974                              <1> 	;	(ES) = REGEN SEGMENT
  1975                              <1> 	; OUTPUT			
  1976                              <1> 	;	(AL) = CHARACTER READ
  1977                              <1> 	;	(AH) = ATTRIBUTE READ
  1978                              <1> 	;
  1979                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1980                              <1> 	;
  1981                              <1> 	; bl = video page number
  1982                              <1> 	;
  1983 00001401 E834010000          <1> 	call	find_position	; get regen location and port address
  1984                              <1> 	; dx = status port
  1985                              <1> 	; esi = cursor location/address
  1986                              <1> p11:
  1987 00001406 FB                  <1> 	sti			; enable interrupts
  1988 00001407 90                  <1> 	nop			; allow for small interupts window
  1989 00001408 FA                  <1> 	cli			; blocks interrupts for single loop
  1990 00001409 EC                  <1> 	in	al, dx		; get status from adapter
  1991 0000140A A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1992 0000140C 75F8                <1> 	jnz	short p11	; wait until it is
  1993                              <1> p12:				; now wait for either retrace high
  1994 0000140E EC                  <1> 	in	al, dx		; get status
  1995 0000140F A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1996 00001411 74FB                <1> 	jz	short p12	; wait until either is active	
  1997                              <1> p13:
  1998 00001413 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1999 00001419 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2000                              <1> 	;
  2001                              <1> 	; al = character, ah = attribute
  2002                              <1> 	;
  2003 0000141C FB                  <1> 	sti
  2004                              <1> 	; bl = video page number 	
  2005                              <1> u3:
  2006                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2007                              <1> 	;;sub	cx, cx		; upper left corner
  2008                              <1> 	;;mov	dh, 25-1 	; lower right row
  2009                              <1> 	;;;mov	dl, [CRT_COLS]
  2010                              <1> 	;mov	dl, 80		; lower right column	
  2011                              <1> 	;;dec	dl
  2012                              <1> 	;;mov	dl, 79
  2013                              <1> 
  2014                              <1> 	;;call	scroll_up	; 04/12/2013
  2015                              <1> 	;;; 11/03/2015
  2016                              <1> 	; 02/09/2014
  2017                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2018                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2019                              <1> 	; 11/03/2015
  2020 0000141D 6629C9              <1> 	sub	cx, cx
  2021 00001420 66BA4F18            <1> 	mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2022                              <1> 	;
  2023 00001424 B001                <1> 	mov	al, 1		; scroll 1 line up
  2024                              <1> 		; ah = attribute
  2025 00001426 E939010000          <1> 	jmp	scroll_up
  2026                              <1> ;u4:
  2027                              <1> 	;;int	10h		; video-call return
  2028                              <1> 				; scroll up the screen
  2029                              <1> 				; tty return
  2030                              <1> ;u5:
  2031                              <1> 	;retn			; return to the caller
  2032                              <1> 
  2033                              <1> u6:				; set-cursor-inc
  2034 0000142B FEC6                <1> 	inc	dh		; next row
  2035                              <1> 				; set cursor
  2036                              <1> ;u7:					
  2037                              <1> 	;;mov	ah, 02h
  2038                              <1> 	;;jmp	short u4 	; establish the new cursor
  2039                              <1> 	;call	set_cpos
  2040                              <1> 	;jmp 	short u5
  2041 0000142D E9AC000000          <1> 	jmp     set_cpos
  2042                              <1> 
  2043                              <1> 	; check for control characters
  2044                              <1> u8:
  2045 00001432 7438                <1> 	je	short u9
  2046 00001434 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2047 00001436 74BF                <1> 	je	short u10
  2048 00001438 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2049 0000143A 7434                <1> 	je	short u11
  2050 0000143C 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2051                              <1> 	;jne	short u0
  2052 0000143E 7424                <1> 	je	short bs	; 12/12/2013
  2053                              <1> 	; 12/12/2013 (tab stop)
  2054 00001440 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2055 00001442 75A1                <1> 	jne	short u0
  2056 00001444 88D0                <1> 	mov	al, dl
  2057 00001446 6698                <1> 	cbw
  2058 00001448 B108                <1> 	mov	cl, 8
  2059 0000144A F6F1                <1> 	div	cl
  2060 0000144C 28E1                <1> 	sub	cl, ah
  2061                              <1> ts:
  2062                              <1> 	; 02/09/2014
  2063                              <1> 	; 01/09/2014
  2064 0000144E B020                <1> 	mov	al, 20h
  2065                              <1> tsloop:
  2066 00001450 6651                <1> 	push	cx
  2067 00001452 6650                <1> 	push	ax
  2068 00001454 30FF                <1> 	xor 	bh, bh
  2069                              <1> 	;mov	bl, [active_page]
  2070 00001456 E878FFFFFF          <1> 	call	m3
  2071 0000145B 6658                <1> 	pop	ax  ; ah = attribute/color
  2072 0000145D 6659                <1> 	pop	cx
  2073 0000145F FEC9                <1> 	dec	cl
  2074 00001461 75ED                <1> 	jnz	short tsloop
  2075 00001463 C3                  <1> 	retn
  2076                              <1> bs:	
  2077                              <1> 	; back space found
  2078                              <1> 
  2079 00001464 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2080                              <1> 	;je	short u7 	; set_cursor
  2081 00001466 7476                <1> 	jz	short set_cpos
  2082 00001468 664A                <1> 	dec	dx     		; no -- just move it back
  2083                              <1> 	;jmp	short u7
  2084 0000146A EB72                <1> 	jmp	short set_cpos
  2085                              <1> 
  2086                              <1> 	; carriage return found
  2087                              <1> u9:
  2088 0000146C B200                <1> 	mov	dl, 0 		; move to first column
  2089                              <1> 	;jmp	short u7
  2090 0000146E EB6E                <1> 	jmp	short set_cpos
  2091                              <1> 
  2092                              <1> 	; line feed found
  2093                              <1> ;u10:
  2094                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2095                              <1> ;	jne	short u6 	; no, just set the cursor
  2096                              <1> ;       jmp     u1              ; yes, scroll the screen
  2097                              <1> 
  2098                              <1> beeper: 
  2099                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2100                              <1> 	; 18/01/2014
  2101                              <1> 	; 03/12/2013
  2102                              <1> 	; bell found
  2103                              <1> u11:
  2104 00001470 FB                  <1> 	sti
  2105 00001471 3A1D[D66D0000]      <1> 	cmp	bl, [active_page]
  2106 00001477 7551                <1> 	jne	short u12	; Do not sound the beep 
  2107                              <1> 				; if it is not written on the active page
  2108 00001479 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2109 0000147D B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2110                              <1> 	;call	beep		; sound the pod bell
  2111                              <1> 	;jmp	short u5 	; tty_return
  2112                              <1> 	;retn
  2113                              <1> 	
  2114                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2115                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2116                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2117                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2118                              <1> 
  2119                              <1> beep:
  2120                              <1> 	; 07/02/2015
  2121                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2122                              <1> 	; 18/01/2014
  2123                              <1> 	; 03/12/2013
  2124                              <1> 	;
  2125                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2126                              <1> 	;
  2127                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2128                              <1> 	;
  2129                              <1> 	; ENTRY:
  2130                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2131                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2132                              <1> 	; EXIT:				:
  2133                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2134                              <1> 
  2135 0000147F 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2136 00001480 FA                  <1> 	cli			; block interrupts during update
  2137 00001481 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2138 00001483 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2139 00001485 EB00                <1> 	jmp	$+2		; I/O delay
  2140 00001487 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2141 00001489 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2142 0000148B EB00                <1> 	jmp	$+2		; I/O delay
  2143 0000148D 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2144 0000148F E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2145 00001491 E461                <1> 	in	al, PORT_B	; get current setting of port
  2146 00001493 88C4                <1> 	mov	ah, al		; save that setting
  2147 00001495 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2148 00001497 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2149                              <1> 	;popf	; 18/01/2014
  2150 00001499 FB                  <1> 	sti
  2151                              <1> g7:				; 1/64 second per count (bl)
  2152 0000149A B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2153 0000149F E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2154 000014A4 FECB                <1> 	dec	bl		; (bl) length count expired?
  2155 000014A6 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2156                              <1> 	;
  2157                              <1> 	;pushf			; save interrupt status
  2158 000014A8 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2159 000014A9 E461                <1> 	in	al, PORT_B	; get current port value
  2160                              <1>         ;or      al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2161 000014AB 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2162 000014AD 20C4                <1>         and	ah, al		; someone turned them off during beep
  2163 000014AF 88E0                <1> 	mov	al, ah		; recover value of port
  2164                              <1>         ;or      al, not (GATE2+SPK2) ; force speaker data off
  2165 000014B1 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2166 000014B3 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2167                              <1> 	;popf			; restore interrupt flag state
  2168 000014B5 FB                  <1> 	sti
  2169 000014B6 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2170 000014BB E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2171                              <1> 	;pushf			; save interrupt status
  2172 000014C0 FA                  <1> 	cli			; block interrupts during update
  2173 000014C1 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2174 000014C3 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2175 000014C5 08E0                <1> 	or	al, ah		; recover value of port_b
  2176 000014C7 E661                <1> 	out	PORT_B, al	; restore speaker status
  2177 000014C9 9D                  <1> 	popf			; restore interrupt flag state
  2178                              <1> u12:	
  2179 000014CA C3                  <1> 	retn
  2180                              <1> 
  2181                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2182                              <1> 
  2183                              <1> WAITF:
  2184                              <1> waitf:
  2185                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2186                              <1> 	; 03/12/2013
  2187                              <1> 	;
  2188                              <1> ;	push ax			; save work register (ah)	
  2189                              <1> ;waitf1:
  2190                              <1> 				; use timer 1 output bits
  2191                              <1> ;	in	al, PORT_B	; read current counter output status
  2192                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2193                              <1> ;	cmp	al, ah		; did it just change
  2194                              <1> ;	je	short waitf1	; wait for a change in output line
  2195                              <1> ;	;
  2196                              <1> ;	mov	ah, al		; save new lflag state
  2197                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2198                              <1> ;	;
  2199                              <1> ;	pop	ax		; restore (ah)
  2200                              <1> ;	retn			; return (cx)=0
  2201                              <1> 
  2202                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2203                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2204                              <1> ; 17/12/2014 (dsectrm2.s)
  2205                              <1> ; WAITF
  2206                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2207                              <1> ;
  2208                              <1> ;---WAITF-----------------------------------------------------------------------
  2209                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2210                              <1> ; ENTRY:
  2211                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2212                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2213                              <1> ; EXIT:
  2214                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2215                              <1> ;	(CX) = 0	
  2216                              <1> ;-------------------------------------------------------------------------------
  2217                              <1> 
  2218                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2219                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2220                              <1> 
  2221                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2222                              <1> 	;PUSH	AX			; SAVE WORK REGISTER (AH)
  2223                              <1> 	; 05/12/2021
  2224 000014CB 50                  <1> 	push	eax
  2225                              <1> 	; 16/12/2014
  2226                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2227 000014CC D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2228                              <1> ;17/12/2014	
  2229                              <1> ;WAITF1:
  2230                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2231                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2232                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2233                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2234                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2235                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2236                              <1> 	;
  2237                              <1> 	; 17/12/2014
  2238                              <1> 	;
  2239                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2240                              <1> 	;
  2241                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2242                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2243                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2244                              <1> WR_STATE_0:
  2245 000014CE E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2246 000014D0 A810                <1> 	TEST	AL,010H
  2247 000014D2 74FA                <1> 	JZ	SHORT WR_STATE_0
  2248                              <1> WR_STATE_1:
  2249 000014D4 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2250 000014D6 A810                <1> 	TEST	AL,010H
  2251 000014D8 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2252 000014DA E2F2                <1>         LOOP    WR_STATE_0
  2253                              <1> 	;
  2254                              <1> 	;POP	AX			; RESTORE (AH)
  2255                              <1> 	; 05/12/2021
  2256 000014DC 58                  <1> 	pop	eax
  2257 000014DD C3                  <1> 	RETn				; (CX) = 0
  2258                              <1> 
  2259                              <1> set_cpos:
  2260                              <1> 	; 27/06/2015
  2261                              <1> 	; 01/09/2014
  2262                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2263                              <1> 	;
  2264                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2265                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2266                              <1> 	;
  2267                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2268                              <1> 	;
  2269                              <1> 	; SET_CPOS
  2270                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2271                              <1> 	;	NEW X-Y VALUES PASSED
  2272                              <1> 	; INPUT
  2273                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2274                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2275                              <1> 	; OUTPUT
  2276                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2277                              <1> 	;
  2278 000014DE 0FB6C3              <1>         movzx   eax, bl  ; BL = video page number ; 27/06/2015 (movzx)
  2279 000014E1 D0E0                <1>         shl     al, 1   ; word offset
  2280 000014E3 BE[C66D0000]        <1> 	mov	esi, cursor_posn
  2281 000014E8 01C6                <1>         add     esi, eax
  2282 000014EA 668916              <1> 	mov	[esi], dx ; save the pointer
  2283 000014ED 381D[D66D0000]      <1> 	cmp	[active_page], bl
  2284 000014F3 7532                <1> 	jne	short m17
  2285                              <1> 	;call	m18	; CURSOR SET
  2286                              <1> ;m17:			; SET_CPOS_RETURN
  2287                              <1> 	; 01/09/2014
  2288                              <1> ;	retn
  2289                              <1> 		; DX  = row/column
  2290                              <1> m18:
  2291 000014F5 E832000000          <1> 	call	position ; determine location in regen buffer	
  2292 000014FA 668B0D[C46D0000]    <1> 	mov	cx, [CRT_START]
  2293 00001501 6601C1              <1> 	add	cx, ax  ; add char position in regen buffer
  2294                              <1> 			; to the start address (offset) for this page
  2295 00001504 66D1E9              <1> 	shr	cx, 1	; divide by 2 for char only count
  2296 00001507 B40E                <1> 	mov	ah, 14	; register number for cursor
  2297                              <1> 	;call	m16	; output value to the 6845	
  2298                              <1> 	;retn
  2299                              <1> 
  2300                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2301                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2302                              <1> m16:
  2303 00001509 FA                  <1> 	cli
  2304                              <1> 	;mov	dx, [addr_6845] ; address register
  2305 0000150A 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2306 0000150E 88E0                <1> 	mov	al, ah	; get value
  2307 00001510 EE                  <1> 	out	dx, al	; register set
  2308 00001511 6642                <1> 	inc	dx	; data register
  2309 00001513 EB00                <1> 	jmp	$+2	; i/o delay
  2310 00001515 88E8                <1> 	mov	al, ch	; data
  2311 00001517 EE                  <1> 	out	dx, al	
  2312 00001518 664A                <1> 	dec	dx	
  2313 0000151A 88E0                <1> 	mov	al, ah
  2314 0000151C FEC0                <1> 	inc	al	; point to other data register
  2315 0000151E EE                  <1> 	out	dx, al	; set for second register
  2316 0000151F 6642                <1> 	inc	dx
  2317 00001521 EB00                <1> 	jmp	$+2	; i/o delay
  2318 00001523 88C8                <1> 	mov	al, cl	; second data value
  2319 00001525 EE                  <1> 	out	dx, al
  2320 00001526 FB                  <1> 	sti
  2321                              <1> m17:
  2322 00001527 C3                  <1> 	retn
  2323                              <1> 
  2324                              <1> set_ctype:
  2325                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2326                              <1> 	;
  2327                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2328                              <1> 
  2329                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2330                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2331                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2332                              <1> ;          OR NO CURSOR AT ALL
  2333                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2334                              <1> 
  2335                              <1> ;------------------------------------------------
  2336                              <1> ; SET_CTYPE
  2337                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2338                              <1> ; INPUT
  2339                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2340                              <1> ; OUTPUT	
  2341                              <1> ;	NONE
  2342                              <1> ;------------------------------------------------
  2343                              <1> 
  2344 00001528 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2345                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2346                              <1> 	;call	m16	; output cx register
  2347                              <1> 	;retn
  2348 0000152A EBDD                <1> 	jmp	m16
  2349                              <1> 
  2350                              <1> 
  2351                              <1> position:
  2352                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2353                              <1> 	; 27/06/2015
  2354                              <1> 	; 02/09/2014
  2355                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2356                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2357                              <1> 	;
  2358                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2359                              <1> 	;
  2360                              <1> 	; POSITION
  2361                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2362                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2363                              <1> 	; INPUT
  2364                              <1> 	;	AX = ROW, COLUMN POSITION
  2365                              <1> 	; OUTPUT
  2366                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2367                              <1> 
  2368                              <1> 		; DX = ROW, COLUMN POSITION
  2369                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2370 0000152C 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2371 0000152E B050                <1> 	mov	al, 80   ; determine bytes to row	
  2372 00001530 F6E6                <1> 	mul	dh 	 ; row value
  2373 00001532 30F6                <1> 	xor	dh, dh   ; 0	
  2374 00001534 6601D0              <1> 	add	ax, dx	 ; add column value to the result
  2375                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2376                              <1> 	; 05/12/2021
  2377 00001537 D1E0                <1> 	shl	eax, 1
  2378                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2379 00001539 C3                  <1> 	retn
  2380                              <1> 
  2381                              <1> find_position:
  2382                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2383                              <1> 	; 27/06/2015
  2384                              <1> 	; 07/09/2014
  2385                              <1> 	; 02/09/2014
  2386                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2387                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2388 0000153A 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2389 0000153D 89CE                <1> 	mov	esi, ecx
  2390                              <1> 	;shl	si, 1
  2391 0000153F D1E6                <1> 	shl	esi, 1 ; 05/12/2021
  2392 00001541 668B96[C66D0000]    <1> 	mov	dx, [esi+cursor_posn]
  2393 00001548 7409                <1> 	jz	short p21
  2394                              <1> 	;xor	si, si
  2395 0000154A 31F6                <1> 	xor	esi, esi ; 05/12/2021
  2396                              <1> p20:
  2397                              <1> 	;add	si, [CRT_LEN]
  2398 0000154C 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2399 00001551 E2F9                <1> 	loop	p20
  2400                              <1> p21:
  2401 00001553 6621D2              <1> 	and	dx, dx
  2402 00001556 7407                <1> 	jz	short p22
  2403 00001558 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2404 0000155D 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2405                              <1> p22:	
  2406                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2407                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2408                              <1> 	;add	dx, 6	; point at status port
  2409 0000155F 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2410                              <1> 	; cx = 0
  2411 00001563 C3                  <1> 	retn
  2412                              <1> 
  2413                              <1> scroll_up:
  2414                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2415                              <1> 	; 16/01/2016
  2416                              <1> 	; 07/09/2014
  2417                              <1> 	; 02/09/2014
  2418                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2419                              <1> 	; 04/04/2014
  2420                              <1> 	; 04/12/2013
  2421                              <1> 	;
  2422                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2423                              <1> 	;
  2424                              <1> 	; SCROLL UP
  2425                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2426                              <1> 	;	ON THE SCREEN
  2427                              <1> 	; INPUT
  2428                              <1> 	;	(AH) = CURRENT CRT MODE
  2429                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2430                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2431                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2432                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2433                              <1> 	;	(DS) = DATA SEGMENT
  2434                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2435                              <1> 	; OUTPUT
  2436                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2437                              <1> 	;
  2438                              <1> 	;	bh = 0  (02/09/2014)
  2439                              <1> 	;
  2440                              <1> 	; ((ah = 3))
  2441                              <1> 	; cl = left upper column
  2442                              <1> 	; ch = left upper row
  2443                              <1> 	; dl = right lower column
  2444                              <1> 	; dh = right lower row
  2445                              <1> 	;
  2446                              <1> 	; al = line count 
  2447                              <1> 	; ah = attribute to be used on blanked line	
  2448                              <1> 	; bl = video page number (0 to 7)
  2449                              <1> 	; 
  2450                              <1> 
  2451                              <1> 	; Test	Line Count
  2452 00001564 08C0                <1> 	or	al, al
  2453 00001566 740C                <1> 	jz	short al_set
  2454 00001568 88F7                <1> 	mov	bh, dh	; subtract lower row from upper row
  2455 0000156A 28EF                <1> 	sub	bh, ch
  2456 0000156C FEC7                <1> 	inc	bh	; adjust difference by 1
  2457 0000156E 38C7                <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2458 00001570 7502                <1> 	jne	short al_set ; if not the we're all set
  2459 00001572 30C0                <1> 	xor	al, al	; otherwise set al to zero
  2460                              <1> al_set:
  2461 00001574 30FF                <1> 	xor	bh, bh	; 0
  2462                              <1> 	;push	ax
  2463 00001576 50                  <1> 	push	eax ; 05/12/2021
  2464                              <1> 	;mov 	esi, [crt_base]
  2465 00001577 BE00800B00          <1>         mov     esi, 0B8000h  
  2466 0000157C 3A1D[D66D0000]      <1>         cmp     bl, [active_page]
  2467 00001582 750B                <1> 	jne	short n0
  2468                              <1> 	;
  2469 00001584 66A1[C46D0000]      <1>         mov     ax, [CRT_START]
  2470 0000158A 6601C6              <1>         add     si, ax
  2471 0000158D EB0F                <1>         jmp     short n1
  2472                              <1> n0:
  2473 0000158F 20DB                <1>         and     bl, bl
  2474 00001591 740B                <1> 	jz	short n1
  2475 00001593 88D8                <1> 	mov	al, bl
  2476                              <1> n0x:
  2477                              <1>         ;add    si, [CRT_LEN]
  2478                              <1>         ;add    esi, 80*25*2 
  2479 00001595 6681C6A00F          <1>         add     si, 80*25*2
  2480 0000159A FEC8                <1>         dec	al
  2481 0000159C 75F7                <1> 	jnz	short n0x
  2482                              <1> n1:	
  2483                              <1>         ;Scroll position
  2484                              <1> 	;push	dx
  2485                              <1> 	; 05/12/2021
  2486 0000159E 52                  <1> 	push	edx
  2487 0000159F 6689CA              <1> 	mov	dx, cx	; now, upper left position in DX
  2488 000015A2 E885FFFFFF          <1> 	call	position
  2489 000015A7 01C6                <1> 	add	esi, eax
  2490 000015A9 89F7                <1> 	mov	edi, esi
  2491                              <1> 	;pop	dx	; lower right position in DX
  2492 000015AB 5A                  <1> 	pop	edx ; 05/12/2021
  2493 000015AC 6629CA              <1> 	sub	dx, cx
  2494 000015AF FEC6                <1> 	inc	dh	; dh = #rows 
  2495 000015B1 FEC2                <1> 	inc	dl	; dl = #cols in block
  2496                              <1> 	;pop	ax	; al = line count, ah = attribute
  2497                              <1> 	; 05/12/2021
  2498 000015B3 58                  <1> 	pop	eax	; al = line count, ah = attribute
  2499 000015B4 31C9                <1> 	xor	ecx, ecx
  2500 000015B6 6689C1              <1> 	mov	cx, ax
  2501                              <1> 	;mov	ah, [CRT_COLS]
  2502 000015B9 B450                <1> 	mov	ah, 80
  2503 000015BB F6E4                <1> 	mul	ah	; determine offset to from address
  2504 000015BD 6601C0              <1> 	add	ax, ax  ; *2 for attribute byte
  2505                              <1> 	;
  2506                              <1> 	;push	ax	; offset 
  2507                              <1> 	;push	dx
  2508                              <1> 	; 05/12/2021
  2509 000015C0 50                  <1> 	push	eax
  2510 000015C1 52                  <1> 	push	edx
  2511                              <1> 	;
  2512                              <1> 	; 04/04/2014
  2513 000015C2 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2514                              <1> n8:                      ; wait_display_enable
  2515 000015C6 EC                  <1>         in      al, dx   ; get port
  2516 000015C7 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2517 000015C9 74FB                <1> 	jz	short n8 ; wait_display_enable
  2518 000015CB B025                <1> 	mov	al, 25h
  2519 000015CD B2D8                <1> 	mov	dl, 0D8h ; address control port
  2520 000015CF EE                  <1> 	out	dx, al	; turn off video during vertical retrace
  2521                              <1> 	;pop	dx	; #rows, #cols
  2522                              <1>        	;pop	ax	; offset
  2523                              <1> 	; 05/12/2021
  2524 000015D0 5A                  <1> 	pop	edx
  2525 000015D1 58                  <1> 	pop	eax
  2526 000015D2 6691                <1> 	xchg	ax, cx	; 
  2527                              <1> 	; ecx = offset, al = line count, ah = attribute
  2528                              <1> ;n9:
  2529 000015D4 08C0                <1> 	or	al, al
  2530 000015D6 7420                <1>         jz      short n3 
  2531 000015D8 01CE                <1>         add     esi, ecx ; from address for scroll
  2532 000015DA 88F7                <1> 	mov	bh, dh  ; #rows in block
  2533 000015DC 28C7                <1> 	sub	bh, al	; #rows to be moved
  2534                              <1> n2:
  2535                              <1> 	; Move rows
  2536 000015DE 88D1                <1> 	mov	cl, dl	; get # of cols to move
  2537 000015E0 56                  <1> 	push	esi
  2538 000015E1 57                  <1> 	push	edi	; save start address
  2539                              <1> n10:
  2540 000015E2 66A5                <1> 	movsw		; move that line on screen
  2541 000015E4 FEC9                <1> 	dec	cl
  2542 000015E6 75FA                <1>         jnz     short n10
  2543 000015E8 5F                  <1> 	pop	edi
  2544 000015E9 5E                  <1> 	pop	esi	; recover addresses
  2545                              <1>         ;mov    cl, [CRT_COLS] 
  2546                              <1> 	;add	cl, cl
  2547                              <1>         ;mov    ecx, 80*2
  2548 000015EA 66B9A000            <1>         mov     cx, 80*2
  2549 000015EE 01CE                <1>         add     esi, ecx  ; next line
  2550 000015F0 01CF                <1>         add     edi, ecx
  2551 000015F2 FECF                <1> 	dec	bh	 ; count of lines to move
  2552 000015F4 75E8                <1> 	jnz	short n2 ; row loop
  2553                              <1> 	; bh = 0
  2554 000015F6 88C6                <1> 	mov	dh, al	 ; #rows	
  2555                              <1> n3:
  2556                              <1> 	; attribute in ah
  2557 000015F8 B020                <1> 	mov	al, ' '	 ; fill with blanks
  2558                              <1> n3x:
  2559                              <1> 	; Clear rows
  2560                              <1>                 ; dh =  #rows
  2561 000015FA 88D1                <1>         mov	cl, dl	; get # of cols to clear
  2562 000015FC 57                  <1>         push    edi     ; save address
  2563                              <1> n11:
  2564 000015FD 66AB                <1>         stosw           ; store fill character
  2565 000015FF FEC9                <1> 	dec	cl
  2566 00001601 75FA                <1>         jnz     short n11
  2567 00001603 5F                  <1>         pop     edi     ; recover address
  2568                              <1> 	;mov	cl, [CRT_COLS]
  2569                              <1> 	;add	cl, cl
  2570                              <1>         ;mov    ecx, 80*2
  2571 00001604 B1A0                <1>         mov	cl, 80*2
  2572 00001606 01CF                <1>         add     edi, ecx
  2573 00001608 FECE                <1> 	dec	dh
  2574 0000160A 75EE                <1> 	jnz	short n3x ; 16/01/2016
  2575                              <1> 	;
  2576 0000160C 3A1D[D66D0000]      <1> 	cmp	bl, [active_page]
  2577 00001612 7507                <1> 	jne	short n6
  2578                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2579 00001614 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2580 00001616 66BAD803            <1> 	mov	dx, 03D8h ; always set color card port
  2581 0000161A EE                  <1> 	out	dx, al
  2582                              <1> n6:
  2583 0000161B C3                  <1> 	retn
  2584                              <1> 
  2585                              <1> 
  2586                              <1> write_c_current:
  2587                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2588                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2589                              <1> 	; 18/01/2014
  2590                              <1> 	; 04/12/2013
  2591                              <1> 	;
  2592                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2593                              <1> 	;
  2594                              <1> 	; WRITE_C_CURRENT
  2595                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2596                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2597                              <1> 	; INPUT	
  2598                              <1> 	;	(AH) = CURRENT CRT MODE
  2599                              <1> 	;	(BH) = DISPLAY PAGE
  2600                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2601                              <1> 	;	(AL) = CHAR TO WRITE
  2602                              <1> 	;	(DS) = DATA SEGMENT
  2603                              <1> 	;	(ES) = REGEN SEGMENT
  2604                              <1> 	; OUTPUT
  2605                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2606                              <1> 
  2607 0000161C FA                  <1> 	cli		
  2608                              <1> 	; bl = video page
  2609                              <1> 	; al = character
  2610                              <1> 	; ah = color/attribute
  2611                              <1> 	;push	dx
  2612                              <1> 	;push	ax	; save character & attribute/color
  2613                              <1> 	; 05/12/2021
  2614 0000161D 52                  <1> 	push	edx
  2615 0000161E 50                  <1> 	push	eax
  2616 0000161F E816FFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2617                              <1> 	; esi = regen location
  2618                              <1> 	; dx = status port
  2619                              <1> 	;
  2620                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2621                              <1> 	;
  2622                              <1> p41:			; wait for horizontal retrace is low or vertical
  2623 00001624 FB                  <1> 	sti		; enable interrupts first
  2624 00001625 3A1D[D66D0000]      <1>         cmp     bl, [active_page]
  2625 0000162B 7510                <1> 	jne	short p44 
  2626 0000162D FA                  <1> 	cli 		; block interrupts for single loop
  2627 0000162E EC                  <1> 	in	al, dx	; get status from the adapter
  2628 0000162F A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2629 00001631 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2630 00001633 A801                <1> 	test	al, RHRZ ; is horizontal retrace low
  2631 00001635 75ED                <1> 	jnz	short p41 ; wait until it is
  2632                              <1> p42:			;  wait for either retrace high
  2633 00001637 EC                  <1> 	in	al, dx ; get status again
  2634 00001638 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2635 0000163A 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2636                              <1> p43:	
  2637 0000163C FB                  <1> 	sti
  2638                              <1> p44:
  2639                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2640                              <1> 	; 05/12/2021
  2641 0000163D 58                  <1> 	pop	eax
  2642 0000163E 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2643                              <1> 				; Retro UNIX 386 v1 feature only!
  2644 00001644 668906              <1> 	mov	[esi], ax
  2645                              <1> 	;pop	dx
  2646                              <1> 	; 05/12/2021
  2647 00001647 5A                  <1> 	pop	edx
  2648 00001648 C3                  <1> 	retn
  2649                              <1> 
  2650                              <1> set_mode:
  2651                              <1> 	; 16/01/2016
  2652                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2653                              <1> 	;
  2654                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2655                              <1> 
  2656                              <1> ;------------------------------------------------------
  2657                              <1> ; SET MODE					      :
  2658                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2659                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2660                              <1> ; INPUT						      :
  2661                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2662                              <1> ; OUTPUT					      :
  2663                              <1> ;	NONE					      :
  2664                              <1> ;------------------------------------------------------
  2665                              <1> 
  2666 00001649 57                  <1> 	push	edi ; 16/01/2016
  2667 0000164A 53                  <1> 	push	ebx
  2668 0000164B 52                  <1> 	push	edx
  2669 0000164C 51                  <1> 	push	ecx ; 16/01/2016
  2670 0000164D 50                  <1>         push    eax
  2671                              <1> 
  2672                              <1> 	;mov	dx, 03D4h 	; address or color card
  2673 0000164E B003                <1> 	mov	al, 3
  2674                              <1> ;M8:
  2675 00001650 A2[D0670000]        <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2676 00001655 B029                <1> 	mov	al, 29h
  2677                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2678 00001657 2437                <1> 	and	al, 037h	; video off, save high resolution bit	
  2679                              <1> 	;push	dx  		; save port value
  2680                              <1> 	;add	dx, 4		; point to control register
  2681 00001659 66BAD803            <1> 	mov	dx, 3D8h
  2682 0000165D EE                  <1> 	out	dx, al		; reset video to off to suppress rolling
  2683                              <1> 	;pop	dx
  2684                              <1> ;M9:
  2685 0000165E BB[08680000]        <1> 	mov	ebx, video_params ; initialization table
  2686                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2687                              <1> 	;xchg 	ah, al
  2688                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2689 00001663 30E4                <1> 	xor	ah, ah		  ; ah is register number during loop 
  2690                              <1> 	
  2691                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2692 00001665 B910000000          <1> 	mov	ecx, 16 ; 16/01/2016
  2693                              <1> M10:			;  initialization loop
  2694 0000166A 88E0                <1> 	mov	al, ah 	; get 6845 register number
  2695 0000166C EE                  <1> 	out	dx, al
  2696 0000166D 6642                <1> 	inc	dx      ; point to data port
  2697 0000166F FEC4                <1> 	inc	ah	; next register value
  2698 00001671 8A03                <1> 	mov	al, [ebx] ; get table value
  2699 00001673 EE                  <1> 	out	dx, al	; out to chip
  2700 00001674 43                  <1> 	inc	ebx	; next in table
  2701 00001675 664A                <1> 	dec	dx	; back to pointer register
  2702 00001677 E2F1                <1> 	loop	M10	; do the whole table
  2703                              <1> 	
  2704                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2705                              <1> 	;xor	ax, ax  
  2706                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2707                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2708                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2709                              <1> 	; black background, light gray characeter color, space character
  2710                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2711                              <1> ;M13:			  ; clear buffer
  2712                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2713                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2714                              <1> 
  2715                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2716                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2717                              <1> 			 ; prepare to output to video enable port
  2718                              <1> 	;add	dx,4	 ; point to the mode control gerister
  2719 00001679 66BAD803            <1> 	mov	dx, 3D8h
  2720                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2721 0000167D B029                <1> 	mov	al, 29h
  2722 0000167F EE                  <1> 	out	dx, al	 ; set video enable port
  2723                              <1> 
  2724                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2725                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2726                              <1> 	;
  2727                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2728                              <1> 	;
  2729                              <1> ;-----	SET CURSOR POSITIONS
  2730                              <1> 	;push	edi
  2731                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2732 00001680 BF[C66D0000]        <1> 	mov	edi, cursor_posn
  2733 00001685 B904000000          <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2734 0000168A 31C0                <1> 	xor	eax, eax
  2735 0000168C F3AB                <1> 	rep 	stosd	; fill with zeroes
  2736                              <1> 	;pop	edi
  2737                              <1> 
  2738                              <1> ;-----	SET UP OVERSCAN REGISTER
  2739 0000168E 6642                <1> 	inc	dx	; set overscan port to a default
  2740 00001690 B030                <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2741                              <1> ;M14:
  2742 00001692 EE                  <1> 	out	dx, al	; output the correct value to 3D9 port
  2743                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2744                              <1> 
  2745                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2746                              <1> 	;
  2747 00001693 58                  <1> 	pop	eax
  2748 00001694 59                  <1> 	pop	ecx ; 16/01/2016
  2749 00001695 5A                  <1> 	pop	edx
  2750 00001696 5B                  <1> 	pop	ebx
  2751 00001697 5F                  <1> 	pop	edi ; 16/01/2016
  2752 00001698 C3                  <1> 	retn
  2753                              <1> 	
  2754                              <1> tty_sw:
  2755                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2756                              <1> 	; 30/06/2015
  2757                              <1> 	; 27/06/2015 
  2758                              <1> 	; 07/09/2014
  2759                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2760                              <1> 	;
  2761                              <1> 	; (Modified registers : EAX)
  2762                              <1> 	;
  2763                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2764                              <1> 	;
  2765                              <1> ;act_disp_page:
  2766                              <1> 	; 30/06/2015
  2767                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2768                              <1> 	; 10/12/2013
  2769                              <1> 	; 04/12/2013
  2770                              <1> 	;
  2771                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2772                              <1> 	;
  2773                              <1> 	; ACT_DISP_PAGE
  2774                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2775                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2776                              <1> 	; INPUT
  2777                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2778                              <1> 	; OUTPUT
  2779                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2780                              <1> 
  2781                              <1> 	;cli
  2782                              <1> 
  2783 00001699 53                  <1> 	push	ebx
  2784                              <1> 	;push	cx
  2785                              <1> 	;push	dx
  2786                              <1> 	; 05/12/2021
  2787 0000169A 51                  <1> 	push	ecx
  2788 0000169B 52                  <1> 	push	edx
  2789                              <1> 	;
  2790 0000169C A2[D66D0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2791                              <1> 	;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2792 000016A1 66B9A00F            <1> 	mov	cx, 25*80*2
  2793                              <1> 	; 27/06/2015
  2794 000016A5 0FB6D8              <1> 	movzx	ebx, al
  2795                              <1> 	;
  2796 000016A8 6698                <1> 	cbw	; 07/09/2014 (ah=0)
  2797 000016AA 66F7E1              <1> 	mul 	cx	; display page times regen length
  2798                              <1> 	; 10/12/2013
  2799 000016AD 66A3[C46D0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2800 000016B3 6689C1              <1> 	mov	cx, ax ; start address to cx
  2801                              <1> 	;sar	cx, 1
  2802 000016B6 66D1E9              <1> 	shr	cx, 1	; divide by 2 for 6845 handling
  2803 000016B9 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2804 000016BB E849FEFFFF          <1> 	call	m16
  2805                              <1> 	;sal	bx, 1
  2806                              <1> 	; 01/09/2014
  2807 000016C0 D0E3                <1> 	shl	bl, 1	; *2 for word offset
  2808 000016C2 81C3[C66D0000]      <1> 	add	ebx, cursor_posn
  2809 000016C8 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2810 000016CB E825FEFFFF          <1> 	call	m18
  2811                              <1> 	;
  2812                              <1> 	;pop	dx
  2813                              <1> 	;pop	cx
  2814                              <1> 	; 05/12/2021
  2815 000016D0 5A                  <1> 	pop	edx
  2816 000016D1 59                  <1> 	pop	ecx
  2817 000016D2 5B                  <1> 	pop	ebx
  2818                              <1> 	;
  2819                              <1> 	;sti
  2820                              <1> 	;
  2821 000016D3 C3                  <1> 	retn
  2822                              <1> 
  2823                              <1> ; % include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2824                              <1> 
  2825                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1856                                  
  1857                                  setup_rtc_int:
  1858                                  ; source: http://wiki.osdev.org/RTC
  1859 000016D4 FA                      	cli		; disable interrupts
  1860                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1861                                  	; in order to change this ...
  1862                                  	; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1863                                  	; (rate must be above 2 and not over 15)
  1864                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1865 000016D5 B08A                    	mov	al, 8Ah 
  1866 000016D7 E670                    	out	70h, al ; set index to register A, disable NMI
  1867 000016D9 90                      	nop
  1868 000016DA E471                    	in	al, 71h ; get initial value of register A
  1869 000016DC 88C4                    	mov 	ah, al
  1870 000016DE 80E4F0                  	and	ah, 0F0h
  1871 000016E1 B08A                    	mov	al, 8Ah 
  1872 000016E3 E670                    	out	70h, al ; reset index to register A
  1873 000016E5 88E0                    	mov	al, ah
  1874 000016E7 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1875 000016E9 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1876                                  	; enable RTC interrupt
  1877 000016EB B08B                    	mov	al, 8Bh ;
  1878 000016ED E670                    	out	70h, al ; select register B and disable NMI
  1879 000016EF 90                      	nop
  1880 000016F0 E471                    	in	al, 71h ; read the current value of register B
  1881 000016F2 88C4                    	mov	ah, al  ;
  1882 000016F4 B08B                    	mov 	al, 8Bh ;
  1883 000016F6 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1884 000016F8 88E0                    	mov	al, ah  ;
  1885 000016FA 0C40                    	or	al, 40h ;
  1886 000016FC E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1887 000016FE FB                      	sti
  1888 000016FF C3                      	retn
  1889                                  
  1890                                  ; Write memory information
  1891                                  ; Temporary Code
  1892                                  ; 06/11/2014
  1893                                  ; 14/08/2015 
  1894                                  memory_info:	
  1895 00001700 A1[AC6D0000]            	mov	eax, [memory_size] ; in pages
  1896 00001705 50                      	push	eax
  1897 00001706 C1E00C                  	shl	eax, 12		   ; in bytes
  1898 00001709 BB0A000000              	mov	ebx, 10
  1899 0000170E 89D9                    	mov	ecx, ebx	   ; 10
  1900 00001710 BE[116A0000]            	mov	esi, mem_total_b_str	
  1901 00001715 E8AE000000              	call	bintdstr
  1902 0000171A 58                      	pop	eax
  1903 0000171B B107                    	mov	cl, 7
  1904 0000171D BE[356A0000]            	mov	esi, mem_total_p_str
  1905 00001722 E8A1000000              	call	bintdstr	
  1906                                  	; 14/08/2015
  1907 00001727 E8B9000000              	call	calc_free_mem
  1908                                  	; edx = calculated free pages
  1909                                  	; ecx = 0
  1910 0000172C A1[B06D0000]            	mov 	eax, [free_pages]
  1911 00001731 39D0                    	cmp	eax, edx ; calculated free mem value 
  1912                                  		; and initial free mem value are same or not?
  1913 00001733 751D                    	jne 	short pmim ; print mem info with '?' if not
  1914 00001735 52                      	push 	edx ; free memory in pages	
  1915                                  	;mov 	eax, edx
  1916 00001736 C1E00C                  	shl	eax, 12 ; convert page count
  1917                                  			; to byte count
  1918 00001739 B10A                    	mov	cl, 10
  1919 0000173B BE[556A0000]            	mov	esi, free_mem_b_str
  1920 00001740 E883000000              	call	bintdstr
  1921 00001745 58                      	pop	eax
  1922 00001746 B107                    	mov	cl, 7
  1923 00001748 BE[796A0000]            	mov	esi, free_mem_p_str
  1924 0000174D E876000000              	call	bintdstr
  1925                                  pmim:
  1926 00001752 BE[FF690000]            	mov	esi, msg_memory_info
  1927                                  pmim_nb:	
  1928 00001757 AC                      	lodsb
  1929 00001758 08C0                    	or	al, al
  1930 0000175A 740D                    	jz	short pmim_ok
  1931 0000175C 56                      	push	esi
  1932 0000175D 31DB                    	xor	ebx, ebx ; 0
  1933                                  			; Video page 0 (bl=0)
  1934 0000175F B407                    	mov	ah, 07h ; Black background, 
  1935                                  			; light gray forecolor
  1936 00001761 E856FCFFFF              	call	write_tty
  1937 00001766 5E                      	pop	esi
  1938 00001767 EBEE                    	jmp	short pmim_nb
  1939                                  pmim_ok:
  1940 00001769 C3                      	retn
  1941                                  
  1942                                  ; Convert binary number to hexadecimal string
  1943                                  ; 10/05/2015  
  1944                                  ; dsectpm.s (28/02/2015)
  1945                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1946                                  ; 01/12/2014
  1947                                  ; 25/11/2014
  1948                                  ;
  1949                                  bytetohex:
  1950                                  	; INPUT ->
  1951                                  	; 	AL = byte (binary number)
  1952                                  	; OUTPUT ->
  1953                                  	;	AX = hexadecimal string
  1954                                  	;
  1955 0000176A 53                      	push	ebx
  1956 0000176B 31DB                    	xor	ebx, ebx
  1957 0000176D 88C3                    	mov	bl, al
  1958 0000176F C0EB04                  	shr	bl, 4
  1959 00001772 8A9B[B8170000]          	mov	bl, [ebx+hexchrs]
  1960 00001778 86D8                    	xchg	bl, al
  1961 0000177A 80E30F                  	and	bl, 0Fh
  1962 0000177D 8AA3[B8170000]          	mov	ah, [ebx+hexchrs]
  1963 00001783 5B                      	pop	ebx	
  1964 00001784 C3                      	retn
  1965                                  
  1966                                  wordtohex:
  1967                                  	; INPUT ->
  1968                                  	; 	AX = word (binary number)
  1969                                  	; OUTPUT ->
  1970                                  	;	EAX = hexadecimal string
  1971                                  	;
  1972 00001785 53                      	push	ebx
  1973 00001786 31DB                    	xor	ebx, ebx
  1974 00001788 86E0                    	xchg	ah, al
  1975 0000178A 6650                    	push	ax
  1976 0000178C 88E3                    	mov	bl, ah
  1977 0000178E C0EB04                  	shr	bl, 4
  1978 00001791 8A83[B8170000]          	mov	al, [ebx+hexchrs]
  1979 00001797 88E3                    	mov	bl, ah
  1980 00001799 80E30F                  	and	bl, 0Fh
  1981 0000179C 8AA3[B8170000]          	mov	ah, [ebx+hexchrs]
  1982 000017A2 C1E010                  	shl	eax, 16
  1983 000017A5 6658                    	pop	ax
  1984 000017A7 5B                      	pop	ebx
  1985 000017A8 EBC0                    	jmp	short bytetohex
  1986                                  	;mov	bl, al
  1987                                  	;shr	bl, 4
  1988                                  	;mov	bl, [ebx+hexchrs]
  1989                                  	;xchg	bl, al	 	
  1990                                  	;and	bl, 0Fh
  1991                                  	;mov	ah, [ebx+hexchrs]
  1992                                  	;pop	ebx	
  1993                                  	;retn
  1994                                  
  1995                                  dwordtohex:
  1996                                  	; INPUT ->
  1997                                  	; 	EAX = dword (binary number)
  1998                                  	; OUTPUT ->
  1999                                  	;	EDX:EAX = hexadecimal string
  2000                                  	;
  2001 000017AA 50                      	push	eax
  2002 000017AB C1E810                  	shr	eax, 16
  2003 000017AE E8D2FFFFFF              	call	wordtohex
  2004 000017B3 89C2                    	mov	edx, eax
  2005 000017B5 58                      	pop	eax
  2006                                  	;call	wordtohex
  2007                                  	;retn
  2008                                  	; 02/01/2022
  2009 000017B6 EBCD                    	jmp	short wordtohex
  2010                                  
  2011                                  ; 10/05/2015
  2012                                  hex_digits:
  2013                                  hexchrs:
  2014 000017B8 303132333435363738-     	db '0123456789ABCDEF'
  2014 000017C1 39414243444546     
  2015                                  
  2016                                  ; Convert binary number to decimal/numeric string
  2017                                  ; 06/11/2014
  2018                                  ; Temporary Code
  2019                                  ;
  2020                                  
  2021                                  bintdstr:
  2022                                  	; EAX = binary number
  2023                                  	; ESI = decimal/numeric string address
  2024                                  	; EBX = divisor (10)
  2025                                  	; ECX = string length (<=10)
  2026 000017C8 01CE                    	add	esi, ecx
  2027                                  btdstr0:
  2028 000017CA 4E                      	dec	esi
  2029 000017CB 31D2                    	xor	edx, edx
  2030 000017CD F7F3                    	div	ebx
  2031 000017CF 80C230                  	add	dl, 30h
  2032 000017D2 8816                    	mov	[esi], dl
  2033 000017D4 FEC9                    	dec	cl
  2034 000017D6 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2035 000017D8 09C0                    	or	eax, eax
  2036 000017DA 75EE                    	jnz	short btdstr0
  2037                                  btdstr1:
  2038 000017DC 4E                      	dec	esi
  2039 000017DD C60620                          mov     byte [esi], 20h ; blank space
  2040 000017E0 FEC9                    	dec	cl
  2041 000017E2 75F8                    	jnz	short btdstr1
  2042                                  btdstr2:
  2043 000017E4 C3                      	retn
  2044                                  
  2045                                  ; Calculate free memory pages on M.A.T.
  2046                                  ; 06/11/2014
  2047                                  ; Temporary Code
  2048                                  ;
  2049                                  
  2050                                  calc_free_mem:
  2051 000017E5 31D2                    	xor	edx, edx
  2052                                  	;xor	ecx, ecx
  2053                                  	;mov	cx, [mat_size] ; in pages
  2054                                  	; 02/01/2022
  2055 000017E7 8B0D[C06D0000]          	mov	ecx, [mat_size] ; in pages
  2056 000017ED C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2057 000017F0 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2058                                  cfm0:
  2059 000017F5 AD                      	lodsd
  2060 000017F6 51                      	push	ecx
  2061 000017F7 B920000000              	mov	ecx, 32
  2062                                  cfm1:
  2063 000017FC D1E8                    	shr	eax, 1
  2064 000017FE 7301                    	jnc	short cfm2
  2065 00001800 42                      	inc	edx
  2066                                  cfm2:
  2067 00001801 E2F9                    	loop	cfm1
  2068 00001803 59                      	pop	ecx
  2069 00001804 E2EF                    	loop	cfm0
  2070 00001806 C3                      	retn
  2071                                  
  2072                                  %include 'diskio.s'  ; 07/03/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 - DISKIO.INC
  2077                              <1> ; Last Modification: 05/12/2021
  2078                              <1> ;
  2079                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2080                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2081                              <1> 
  2082                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2083                              <1> 
  2084                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2085                              <1> 
  2086                              <1> ; 06/02/2015
  2087                              <1> diskette_io:
  2088 00001807 9C                  <1> 	pushfd
  2089 00001808 0E                  <1> 	push 	cs
  2090 00001809 E809000000          <1> 	call 	DISKETTE_IO_1
  2091 0000180E C3                  <1> 	retn
  2092                              <1> 	
  2093                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2094                              <1> ;//////////////////////////////////////////////////////
  2095                              <1> 
  2096                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2097                              <1> ; 20/02/2015
  2098                              <1> ; 06/02/2015 (unix386.s)
  2099                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2100                              <1> ;
  2101                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2102                              <1> ;
  2103                              <1> ; ADISK.EQU
  2104                              <1> 
  2105                              <1> ;----- Wait control constants 
  2106                              <1> 
  2107                              <1> ;amount of time to wait while RESET is active.
  2108                              <1> 
  2109                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2110                              <1> 					;at 250 KBS xfer rate.
  2111                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2112                              <1> 
  2113                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2114                              <1> 					;status register to become valid
  2115                              <1> 					;before re-reading.
  2116                              <1> 
  2117                              <1> ;After sending a byte to NEC, status register may remain
  2118                              <1> ;incorrectly set for 24 us.
  2119                              <1> 
  2120                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2121                              <1> 					;RQM low.
  2122                              <1> 
  2123                              <1> ; COMMON.MAC
  2124                              <1> ;
  2125                              <1> ;	Timing macros
  2126                              <1> ;
  2127                              <1> 
  2128                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2129                              <1> 		jmp short $+2
  2130                              <1> %endmacro		
  2131                              <1> 
  2132                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2133                              <1> 		jmp short $+2
  2134                              <1> 		jmp short $+2
  2135                              <1> %endmacro
  2136                              <1> 
  2137                              <1> %macro		NEWIODELAY 0
  2138                              <1> 		out	0EBh,al
  2139                              <1> %endmacro 
  2140                              <1> 
  2141                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2142                              <1> ;;; WAIT_FOR_MEM
  2143                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2144                              <1> ;WAIT_FDU_INT_HI	equ	1
  2145                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2146                              <1> ;;; WAIT_FOR_PORT
  2147                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2148                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2149                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2150                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2151                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2152                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2153                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2154                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2155                              <1> ;;; WAIT_REFRESH
  2156                              <1> ;amount of time to wait for head settle, per unit in parameter
  2157                              <1> ;table = 1 ms.
  2158                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2159                              <1> 
  2160                              <1> 
  2161                              <1> ; //////////////// DISKETTE I/O ////////////////
  2162                              <1> 
  2163                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2164                              <1> 
  2165                              <1> ;----------------------------------------
  2166                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2167                              <1> ;----------------------------------------
  2168                              <1> 
  2169                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2170                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2171                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2172                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2173                              <1> 
  2174                              <1> ;----------------------------------------
  2175                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2176                              <1> ;-------------------------------------------------------------------------------
  2177                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2178                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2179                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2180                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2181                              <1> 
  2182                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2183                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2184                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2185                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2186                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2187                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2188                              <1> 
  2189                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2190                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2191                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2192                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2193                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2194                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2195                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2196                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2197                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2198                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2199                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2200                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2201                              <1> 
  2202                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2203                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2204                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2205                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2206                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2207                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2208                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2209                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2210                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2211                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2212                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2213                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2214                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2215                              <1> 
  2216                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2217                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2218                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2219                              <1> 
  2220                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2221                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2222                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2223                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2224                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2225                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2226                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2227                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2228                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2229                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2230                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2231                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2232                              <1> 
  2233                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2234                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2235                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2236                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2237                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2238                              <1> 
  2239                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2240                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2241                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2242                              <1> INTA01		EQU	021H		; 8259 PORT
  2243                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2244                              <1> INTB01		EQU	0A1H		;
  2245                              <1> 
  2246                              <1> ;-------------------------------------------------------------------------------
  2247                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2248                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2249                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2250                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2251                              <1> ;-------------------------------------------------------------------------------
  2252                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2253                              <1> 
  2254                              <1> ;-------------------------------------------------------------------------------
  2255                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2256                              <1> 
  2257                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2258                              <1> ; (unix386.s <-- dsectrm2.s)
  2259                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2260                              <1> 
  2261                              <1> ; 10/12/2014
  2262                              <1> ;
  2263                              <1> ;int40h:
  2264                              <1> ;	pushf
  2265                              <1> ;	push 	cs
  2266                              <1> ;	;cli
  2267                              <1> ;	call 	DISKETTE_IO_1
  2268                              <1> ;	retn
  2269                              <1> 
  2270                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2271                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2272                              <1> ;
  2273                              <1> 
  2274                              <1> ;-- INT13H ---------------------------------------------------------------------
  2275                              <1> ; DISKETTE I/O
  2276                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2277                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2278                              <1> ; INPUT
  2279                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2280                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2281                              <1> ;		ON ALL DRIVES
  2282                              <1> ;------------------------------------------------------------------------------- 
  2283                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2284                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2285                              <1> ;-------------------------------------------------------------------------------
  2286                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2287                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2288                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2289                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2290                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2291                              <1> ;		320/360	320/360	    0-39
  2292                              <1> ;		320/360	1.2M	    0-39
  2293                              <1> ;		1.2M	1.2M	    0-79
  2294                              <1> ;		720K	720K	    0-79
  2295                              <1> ;		1.44M	1.44M	    0-79	
  2296                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2297                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2298                              <1> ;		320/360	320/360	     1-8/9
  2299                              <1> ;		320/360	1.2M	     1-8/9
  2300                              <1> ;		1.2M	1.2M	     1-15
  2301                              <1> ;		720K	720K	     1-9
  2302                              <1> ;		1.44M	1.44M	     1-18		
  2303                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2304                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2305                              <1> ;		320/360	320/360	        8/9
  2306                              <1> ;		320/360	1.2M	        8/9
  2307                              <1> ;		1.2M	1.2M		15
  2308                              <1> ;		720K	720K		9
  2309                              <1> ;		1.44M	1.44M		18
  2310                              <1> ;
  2311                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2312                              <1> ;
  2313                              <1> ;-------------------------------------------------------------------------------
  2314                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2315                              <1> ;-------------------------------------------------------------------------------
  2316                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2317                              <1> ;-------------------------------------------------------------------------------
  2318                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2319                              <1> ;-------------------------------------------------------------------------------
  2320                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2321                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2322                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2323                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2324                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2325                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2326                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2327                              <1> ;		READ/WRITE ACCESS.
  2328                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2329                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2330                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2331                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2332                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2333                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2334                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2335                              <1> ;
  2336                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2337                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2338                              <1> ;		---------------------------------------------
  2339                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2340                              <1> ;		---------------------------------------------
  2341                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2342                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2343                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2344                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2345                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2346                              <1> ;		---------------------------------------------
  2347                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2348                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2349                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2350                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2351                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2352                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2353                              <1> ;-------------------------------------------------------------------------------
  2354                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2355                              <1> ;	REGISTERS
  2356                              <1> ;	  INPUT
  2357                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2358                              <1> ;	  OUTPUT
  2359                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2360                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2361                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2362                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2363                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2364                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2365                              <1> ;	    (BH) - 0
  2366                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2367                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2368                              <1> ;	    (AX) - 0
  2369                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2370                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2371                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2372                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2373                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2374                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2375                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2376                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2377                              <1> ;-------------------------------------------------------------------------------
  2378                              <1> ;	(AH)= 15H  READ DASD TYPE
  2379                              <1> ;	OUTPUT REGISTERS
  2380                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2381                              <1> ;		00 - DRIVE NOT PRESENT	
  2382                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2383                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2384                              <1> ;		03 - RESERVED (FIXED DISK)
  2385                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2386                              <1> ;-------------------------------------------------------------------------------
  2387                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2388                              <1> ;	OUTPUT REGISTERS
  2389                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2390                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2391                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2392                              <1> ;-------------------------------------------------------------------------------
  2393                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2394                              <1> ;	INPUT REGISTERS
  2395                              <1> ;	(AL) -	00 - NOT USED	
  2396                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2397                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2398                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2399                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2400                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2401                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2402                              <1> ;-------------------------------------------------------------------------------
  2403                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2404                              <1> ;	INPUT REGISTERS
  2405                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2406                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2407                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2408                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2409                              <1> ;	OUTPUT REGISTERS:
  2410                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2411                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2412                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2413                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2414                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2415                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2416                              <1> ;-------------------------------------------------------------------------------
  2417                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2418                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2419                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2420                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2421                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2422                              <1> ;		CHANGE ERROR CODE
  2423                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2424                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2425                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2426                              <1> ;
  2427                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2428                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2429                              <1> ;-------------------------------------------------------------------------------
  2430                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2431                              <1> ;	AH = STATUS OF OPERATION
  2432                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2433                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2434                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2435                              <1> ;		TYPE AH=(15)).
  2436                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2437                              <1> ;	FOR READ/WRITE/VERIFY
  2438                              <1> ;		DS,BX,DX,CX PRESERVED
  2439                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2440                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2441                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2442                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2443                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2444                              <1> ;-------------------------------------------------------------------------------
  2445                              <1> ;
  2446                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2447                              <1> ;
  2448                              <1> ;   -----------------------------------------------------------------
  2449                              <1> ;   |       |       |       |       |       |       |       |       |
  2450                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2451                              <1> ;   |       |       |       |       |       |       |       |       |
  2452                              <1> ;   -----------------------------------------------------------------
  2453                              <1> ;	|	|	|	|	|	|	|	|
  2454                              <1> ;	|	|	|	|	|	-----------------
  2455                              <1> ;	|	|	|	|	|		|
  2456                              <1> ;	|	|	|	|    RESERVED		|
  2457                              <1> ;	|	|	|	|		  PRESENT STATE
  2458                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2459                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2460                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2461                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2462                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2463                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2464                              <1> ;	|	|	|	|	110: RESERVED
  2465                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2466                              <1> ;	|	|	|	|
  2467                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2468                              <1> ;	|	|	|
  2469                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2470                              <1> ;	|	|			DRIVE)
  2471                              <1> ;	|	|
  2472                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2473                              <1> ;
  2474                              <1> ;						00: 500 KBS
  2475                              <1> ;						01: 300 KBS
  2476                              <1> ;						10: 250 KBS
  2477                              <1> ;						11: RESERVED
  2478                              <1> ;
  2479                              <1> ;
  2480                              <1> ;-------------------------------------------------------------------------------
  2481                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2482                              <1> ;-------------------------------------------------------------------------------
  2483                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2484                              <1> ;-------------------------------------------------------------------------------
  2485                              <1> 
  2486                              <1> struc MD
  2487 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2488 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2489 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2490 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2491 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2492 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2493 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2494 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2495 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2496 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2497 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2498 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2499 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2500                              <1> endstruc
  2501                              <1> 
  2502                              <1> BIT7OFF	EQU	7FH
  2503                              <1> BIT7ON	EQU	80H
  2504                              <1> 
  2505                              <1> ;;int13h: ; 16/02/2015
  2506                              <1> ;; 16/02/2015 - 21/02/2015
  2507                              <1> int40h:
  2508 0000180F 9C                  <1> 	pushfd
  2509 00001810 0E                  <1> 	push 	cs
  2510 00001811 E801000000          <1> 	call 	DISKETTE_IO_1
  2511 00001816 C3                  <1> 	retn	
  2512                              <1> 
  2513                              <1> DISKETTE_IO_1:
  2514                              <1> 
  2515 00001817 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2516 00001818 55                  <1> 	PUSH	eBP			; USER REGISTER
  2517 00001819 57                  <1> 	PUSH	eDI			; USER REGISTER
  2518 0000181A 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2519 0000181B 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2520 0000181C 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2521 0000181D 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2522                              <1> 					; [BP]   = SECTOR #
  2523                              <1> 					; [BP+1] = TRACK #
  2524                              <1> 					; [BP+2] = BUFFER OFFSET
  2525                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2526                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2527                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2528                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2529                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2530                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2531                              <1> 					; BH/[BP+3] = 0
  2532                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2533                              <1> 					; DH/[BP+5] = MAX HEAD #
  2534                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2535 0000181F 06                  <1> 	push	es ; 06/02/2015	
  2536 00001820 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2537 00001821 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2538                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2539                              <1> 	;mov	cx, cs
  2540                              <1> 	;mov	ds, cx
  2541 00001822 66B91000            <1> 	mov	cx, KDATA
  2542 00001826 8ED9                <1>         mov     ds, cx
  2543 00001828 8EC1                <1>         mov     es, cx
  2544                              <1> 
  2545                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2546 0000182A 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2547 0000182D 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2548 0000182F B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2549                              <1> OK_FUNC:
  2550 00001831 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2551 00001834 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2552 00001836 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2553 00001839 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2554 0000183B 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2555 0000183E 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2556 00001840 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2557                              <1> OK_DRV:
  2558 00001842 31C9                <1> 	xor	ecx, ecx
  2559                              <1> 	;mov	esi, ecx ; 08/02/2015
  2560                              <1> 	; 05/12/2021
  2561 00001844 89CE                <1> 	mov	esi, ecx
  2562 00001846 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2563 00001848 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2564                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2565                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2566 0000184A C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2567 0000184D BB[85180000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2568 00001852 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2569 00001854 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2570 00001856 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2571 00001858 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2572 0000185B 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2573                              <1> 	;
  2574                              <1> 	; 11/12/2014
  2575 0000185E 8815[91680000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2576                              <1> 	;
  2577 00001864 8A25[2C6E0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2578 0000186A C605[2C6E0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2579                              <1> 
  2580                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2581                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2582                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2583                              <1> ;
  2584                              <1> ;		DI	: DRIVE #
  2585                              <1> ;		SI-HI	: HEAD #
  2586                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2587                              <1> ;		ES	: BUFFER SEGMENT
  2588                              <1> ;		[BP]	: SECTOR #
  2589                              <1> ;		[BP+1]	: TRACK #
  2590                              <1> ;		[BP+2]	: BUFFER OFFSET
  2591                              <1> ;
  2592                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2593                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2594                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2595                              <1> ;	SPECIFIC ERROR CODE.
  2596                              <1> ;
  2597                              <1> 					; (AH) = @DSKETTE_STATUS
  2598 00001871 FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2599 00001873 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2600 00001874 1F                  <1> 	POP	DS
  2601 00001875 07                  <1> 	pop	es	; 06/02/2015
  2602 00001876 59                  <1> 	POP	eCX
  2603 00001877 5B                  <1> 	POP	eBX
  2604 00001878 5A                  <1> 	POP	eDX
  2605 00001879 5F                  <1> 	POP	eDI
  2606 0000187A 89E5                <1> 	MOV	eBP, eSP
  2607 0000187C 50                  <1> 	PUSH	eAX
  2608 0000187D 9C                  <1> 	PUSHFd
  2609 0000187E 58                  <1> 	POP	eAX
  2610                              <1> 	;MOV	[BP+6], AX
  2611 0000187F 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2612 00001882 58                  <1> 	POP	eAX
  2613 00001883 5D                  <1> 	POP	eBP
  2614 00001884 CF                  <1> 	IRETd
  2615                              <1> 
  2616                              <1> ;-------------------------------------------------------------------------------
  2617                              <1> ; DW --> dd (06/02/2015)
  2618 00001885 [E9180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2619 00001889 [5E190000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2620 0000188D [6E190000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2621 00001891 [7F190000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2622 00001895 [90190000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2623 00001899 [A1190000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2624 0000189D [251A0000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2625 000018A1 [251A0000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2626 000018A5 [311A0000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2627 000018A9 [251A0000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2628 000018AD [251A0000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2629 000018B1 [251A0000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2630 000018B5 [251A0000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2631 000018B9 [251A0000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2632 000018BD [251A0000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2633 000018C1 [251A0000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2634 000018C5 [251A0000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2635 000018C9 [251A0000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2636 000018CD [251A0000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2637 000018D1 [251A0000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2638 000018D5 [251A0000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2639 000018D9 [F01A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2640 000018DD [181B0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2641 000018E1 [511B0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2642 000018E5 [D21B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2643                              <1> FNC_TAE EQU     $                       ; END
  2644                              <1> 
  2645                              <1> ;-------------------------------------------------------------------------------
  2646                              <1> ; DISK_RESET	(AH = 00H)	
  2647                              <1> ;		RESET THE DISKETTE SYSTEM.
  2648                              <1> ;
  2649                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2650                              <1> ;-------------------------------------------------------------------------------
  2651                              <1> DSK_RESET:
  2652 000018E9 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2653 000018ED FA                  <1> 	CLI				; NO INTERRUPTS
  2654 000018EE A0[2A6E0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2655 000018F3 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2656 000018F5 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2657                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2658 000018F8 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2659 000018FA EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2660 000018FB C605[296E0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2661                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2662                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2663                              <1> 					;      PULSE WIDTH)
  2664                              <1> 	; 19/12/2014
  2665                              <1> 	NEWIODELAY
  2138 00001902 E6EB                <2>  out 0EBh,al
  2666                              <1> 
  2667                              <1> 	; 17/12/2014 
  2668                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2669 00001904 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2670                              <1> wdw1:
  2671                              <1> 	NEWIODELAY   ; 27/02/2015
  2138 00001909 E6EB                <2>  out 0EBh,al
  2672 0000190B E2FC                <1> 	loop	wdw1
  2673                              <1> 	;
  2674 0000190D 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2675 0000190F EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2676                              <1> 	; 16/12/2014
  2677                              <1> 	IODELAY
  2133 00001910 EB00                <2>  jmp short $+2
  2134 00001912 EB00                <2>  jmp short $+2
  2678                              <1> 	;
  2679                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2680 00001914 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2681 00001919 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2682 0000191B 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2683                              <1> NXT_DRV:
  2684                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2685                              <1> 	; 05/12/2021
  2686 0000191F 51                  <1> 	push	ecx
  2687 00001920 B8[54190000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2688 00001925 50                  <1> 	PUSH	eAX			; "
  2689 00001926 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2690 00001928 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2691 0000192D 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2692 0000192E E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2693                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2694                              <1> 	; 05/12/2021
  2695 00001933 59                  <1> 	pop	ecx
  2696 00001934 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2697 00001936 3A0D[2D6E0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2698 0000193C 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2699 0000193E FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2700 00001940 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2701 00001943 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2702                              <1> 	;
  2703 00001945 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2704                              <1> RESBAC:
  2705 0000194A E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2706                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2707                              <1> 	; 05/12/2021
  2708 0000194F 89F3                <1> 	mov	ebx, esi
  2709 00001951 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2710 00001953 C3                  <1> 	RETn		
  2711                              <1> DR_POP_ERR:
  2712                              <1> 	;POP	CX			; CLEAR STACK
  2713                              <1> 	; 05/12/2021
  2714 00001954 59                  <1> 	pop	ecx
  2715                              <1> DR_ERR:
  2716 00001955 800D[2C6E0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2717 0000195C EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2718                              <1> 
  2719                              <1> ;-------------------------------------------------------------------------------
  2720                              <1> ; DISK_STATUS	(AH = 01H)
  2721                              <1> ;	DISKETTE STATUS.
  2722                              <1> ;
  2723                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2724                              <1> ;
  2725                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2726                              <1> ;-------------------------------------------------------------------------------
  2727                              <1> DSK_STATUS:
  2728 0000195E 8825[2C6E0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2729 00001964 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2730                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2731                              <1> 	; 05/12/2021
  2732 00001969 89F3                <1> 	mov	ebx, esi
  2733 0000196B 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2734 0000196D C3                  <1> 	RETn		
  2735                              <1> 
  2736                              <1> ;-------------------------------------------------------------------------------
  2737                              <1> ; DISK_READ	(AH = 02H)	
  2738                              <1> ;	DISKETTE READ.
  2739                              <1> ;
  2740                              <1> ; ON ENTRY:	DI	: DRIVE #
  2741                              <1> ;		SI-HI	: HEAD #
  2742                              <1> ;		SI-LOW	: # OF SECTORS
  2743                              <1> ;		ES	: BUFFER SEGMENT
  2744                              <1> ;		[BP]	: SECTOR #
  2745                              <1> ;		[BP+1]	: TRACK #
  2746                              <1> ;		[BP+2]	: BUFFER OFFSET
  2747                              <1> ;
  2748                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2749                              <1> ;-------------------------------------------------------------------------------
  2750                              <1> 
  2751                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2752                              <1> 
  2753                              <1> DSK_READ:
  2754 0000196E 8025[2A6E0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2755 00001975 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2756 00001979 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2757 0000197E C3                  <1> 	RETn
  2758                              <1> 
  2759                              <1> ;-------------------------------------------------------------------------------
  2760                              <1> ; DISK_WRITE	(AH = 03H)
  2761                              <1> ;	DISKETTE WRITE.
  2762                              <1> ;
  2763                              <1> ; ON ENTRY:	DI	: DRIVE #
  2764                              <1> ;		SI-HI	: HEAD #
  2765                              <1> ;		SI-LOW	: # OF SECTORS
  2766                              <1> ;		ES	: BUFFER SEGMENT
  2767                              <1> ;		[BP]	: SECTOR #
  2768                              <1> ;		[BP+1]	: TRACK #
  2769                              <1> ;		[BP+2]	: BUFFER OFFSET
  2770                              <1> ;
  2771                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2772                              <1> ;-------------------------------------------------------------------------------
  2773                              <1> 
  2774                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2775                              <1> 
  2776                              <1> DSK_WRITE:
  2777 0000197F 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2778 00001983 800D[2A6E0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2779 0000198A E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2780 0000198F C3                  <1> 	RETn
  2781                              <1> 
  2782                              <1> ;-------------------------------------------------------------------------------
  2783                              <1> ; DISK_VERF	(AH = 04H)
  2784                              <1> ;	DISKETTE VERIFY.
  2785                              <1> ;
  2786                              <1> ; ON ENTRY:	DI	: DRIVE #
  2787                              <1> ;		SI-HI	: HEAD #
  2788                              <1> ;		SI-LOW	: # OF SECTORS
  2789                              <1> ;		ES	: BUFFER SEGMENT
  2790                              <1> ;		[BP]	: SECTOR #
  2791                              <1> ;		[BP+1]	: TRACK #
  2792                              <1> ;		[BP+2]	: BUFFER OFFSET
  2793                              <1> ;
  2794                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2795                              <1> ;-------------------------------------------------------------------------------
  2796                              <1> DSK_VERF:
  2797 00001990 8025[2A6E0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2798 00001997 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2799 0000199B E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2800 000019A0 C3                  <1> 	RETn
  2801                              <1> 
  2802                              <1> ;-------------------------------------------------------------------------------
  2803                              <1> ; DISK_FORMAT	(AH = 05H)
  2804                              <1> ;	DISKETTE FORMAT.
  2805                              <1> ;
  2806                              <1> ; ON ENTRY:	DI	: DRIVE #
  2807                              <1> ;		SI-HI	: HEAD #
  2808                              <1> ;		SI-LOW	: # OF SECTORS
  2809                              <1> ;		ES	: BUFFER SEGMENT
  2810                              <1> ;		[BP]	: SECTOR #
  2811                              <1> ;		[BP+1]	: TRACK #
  2812                              <1> ;		[BP+2]	: BUFFER OFFSET
  2813                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2814                              <1> ;
  2815                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2816                              <1> ;-------------------------------------------------------------------------------
  2817                              <1> DSK_FORMAT:
  2818 000019A1 E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2819 000019A6 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2820 000019AB 800D[2A6E0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2821 000019B2 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2822 000019B7 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2823 000019B9 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2824 000019BE E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2825 000019C3 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2826 000019C5 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2827                              <1> FM_WR:
  2828 000019CA E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2829 000019CF 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2830 000019D1 B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2831 000019D3 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2832 000019D8 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2833 000019DA B8[161A0000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2834 000019DF 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2835 000019E0 B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2836 000019E2 E80E090000          <1> 	CALL	GET_PARM
  2837 000019E7 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2838 000019EC B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2839 000019EE E802090000          <1> 	CALL	GET_PARM
  2840 000019F3 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2841 000019F8 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2842 000019FA E8F6080000          <1> 	CALL	GET_PARM
  2843 000019FF E8F7090000          <1> 	CALL	NEC_OUTPUT
  2844 00001A04 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2845 00001A06 E8EA080000          <1> 	CALL	GET_PARM
  2846 00001A0B E8EB090000          <1> 	CALL	NEC_OUTPUT
  2847 00001A10 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2848 00001A11 E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2849                              <1> FM_DON:
  2850 00001A16 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2851 00001A1B E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2852                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2853 00001A20 89F3                <1> 	mov	ebx, esi ; 05/12/2021
  2854 00001A22 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2855 00001A24 C3                  <1> 	RETn
  2856                              <1> 
  2857                              <1> ;-------------------------------------------------------------------------------
  2858                              <1> ; FNC_ERR
  2859                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2860                              <1> ;	SET BAD COMMAND IN STATUS.
  2861                              <1> ;
  2862                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2863                              <1> ;-------------------------------------------------------------------------------
  2864                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2865                              <1> 	;MOV	AX,SI			; RESTORE AL
  2866                              <1> 	; 05/12/2021
  2867 00001A25 89F0                <1> 	mov	eax, esi
  2868 00001A27 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2869 00001A29 8825[2C6E0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2870 00001A2F F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2871 00001A30 C3                  <1> 	RETn
  2872                              <1> 
  2873                              <1> ;-------------------------------------------------------------------------------
  2874                              <1> ; DISK_PARMS	(AH = 08H)	
  2875                              <1> ;	READ DRIVE PARAMETERS.
  2876                              <1> ;
  2877                              <1> ; ON ENTRY:	DI : DRIVE #
  2878                              <1> ;
  2879                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2880                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2881                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2882                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2883                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2884                              <1> ;		BH/[BP+3] = 0
  2885                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2886                              <1> ;		DH/[BP+5] = MAX HEAD #
  2887                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2888                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2889                              <1> ;		AX        = 0
  2890                              <1> ;
  2891                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2892                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2893                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2894                              <1> ;		       CALLER.
  2895                              <1> ;-------------------------------------------------------------------------------
  2896                              <1> DSK_PARMS:
  2897 00001A31 E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2898                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2899 00001A36 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2900 00001A38 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2901                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2902                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2903                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2904                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2905                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2906                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2907                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2908                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2909                              <1> 	;sub	edx, edx
  2910 00001A3B 66A1[9E680000]      <1> 	mov     ax, [fd0_type]
  2911 00001A41 6621C0              <1> 	and     ax, ax
  2912 00001A44 7473                <1> 	jz      short NON_DRV
  2913 00001A46 FEC2                <1> 	inc     dl
  2914 00001A48 20E4                <1> 	and     ah, ah
  2915 00001A4A 7402                <1> 	jz      short STO_DL
  2916 00001A4C FEC2                <1> 	inc     dl
  2917                              <1> STO_DL:
  2918                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2919 00001A4E 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2920 00001A51 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2921 00001A55 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2922                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2923 00001A57 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2924 00001A5B E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2925                              <1> 	;;20/02/2015
  2926                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2927                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2928 00001A60 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2929 00001A62 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2930 00001A67 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2931                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2932 00001A69 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2933 00001A6C 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2934 00001A6F 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2935 00001A72 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2936                              <1> CHK_EST:
  2937 00001A74 8AA7[396E0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2938 00001A7A F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2939 00001A7D 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2940                              <1> USE_EST:
  2941 00001A7F 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2942 00001A82 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2943 00001A85 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2944                              <1> 
  2945                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2946                              <1> 
  2947 00001A87 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2948 00001A89 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2949 00001A8E 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2950 00001A91 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2951 00001A94 F687[396E0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2952 00001A9B 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2953                              <1> 
  2954                              <1> ;-----	IT IS 1.44 MB DRIVE
  2955                              <1> 
  2956                              <1> PARM144:
  2957 00001A9D B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2958 00001A9F E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2959 00001AA4 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2960 00001AA7 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2961                              <1> STO_CX:
  2962 00001AAA 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2963                              <1> ES_DI:
  2964                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2965 00001AAD 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2966                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2967                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2968                              <1> DP_OUT:
  2969 00001AB0 E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2970                              <1> 	;XOR	AX,AX			; CLEAR
  2971                              <1> 	; 05/12/2021
  2972 00001AB5 31C0                <1> 	xor	eax, eax
  2973 00001AB7 F8                  <1> 	CLC
  2974 00001AB8 C3                  <1> 	RETn
  2975                              <1> 
  2976                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2977                              <1> 
  2978                              <1> NON_DRV:
  2979                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2980 00001AB9 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2981                              <1> NON_DRV1:
  2982 00001ABC 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2983 00001AC1 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2984                              <1> 
  2985                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2986                              <1> 	
  2987 00001AC3 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2988                              <1> 	;MOV	AX,SI			; RESTORE AL
  2989 00001AC8 89F0                <1> 	mov	eax, esi ; 05/12/2021
  2990 00001ACA B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2991 00001ACC F9                  <1> 	STC
  2992 00001ACD C3                  <1> 	RETn
  2993                              <1> 
  2994                              <1> NON_DRV2:
  2995                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2996 00001ACE 31C0                <1> 	xor	eax, eax	
  2997 00001AD0 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2998                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2999 00001AD4 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  3000                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  3001 00001AD7 89450C              <1> 	mov	[ebp+12], eax
  3002                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  3003 00001ADA EBD4                <1> 	JMP	SHORT DP_OUT
  3004                              <1> 
  3005                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  3006                              <1> 
  3007                              <1> USE_EST2:
  3008 00001ADC B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  3009 00001ADE E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3010 00001AE3 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3011 00001AE6 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  3012 00001AE9 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3013 00001AEC 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  3014 00001AEE EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  3015                              <1> 
  3016                              <1> ;-------------------------------------------------------------------------------
  3017                              <1> ; DISK_TYPE (AH = 15H)	
  3018                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  3019                              <1> ;
  3020                              <1> ;  ON ENTRY:	DI = DRIVE #
  3021                              <1> ;
  3022                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  3023                              <1> ;-------------------------------------------------------------------------------
  3024                              <1> DSK_TYPE:
  3025 00001AF0 E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3026 00001AF5 8A87[396E0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  3027 00001AFB 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  3028 00001AFD 7415                <1> 	JZ	short NO_DRV
  3029 00001AFF B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3030 00001B01 A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3031 00001B03 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3032 00001B05 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3033                              <1> DT_BACK:
  3034                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3035 00001B07 50                  <1> 	push	eax ; 05/12/2021
  3036 00001B08 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3037                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3038 00001B0D 58                  <1> 	pop	eax ; 05/12/2021
  3039 00001B0E F8                  <1> 	CLC				; NO ERROR
  3040                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3041                              <1> 	; 05/12/2021
  3042 00001B0F 89F3                <1> 	mov	ebx, esi
  3043 00001B11 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3044 00001B13 C3                  <1> 	RETn
  3045                              <1> NO_DRV:	
  3046 00001B14 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3047 00001B16 EBEF                <1> 	JMP	SHORT DT_BACK
  3048                              <1> 
  3049                              <1> ;-------------------------------------------------------------------------------
  3050                              <1> ; DISK_CHANGE	(AH = 16H)
  3051                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3052                              <1> ;
  3053                              <1> ; ON ENTRY:	DI = DRIVE #
  3054                              <1> ;
  3055                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3056                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3057                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3058                              <1> ;-------------------------------------------------------------------------------
  3059                              <1> DSK_CHANGE:
  3060 00001B18 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3061 00001B1D 8A87[396E0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3062 00001B23 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3063 00001B25 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3064 00001B27 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3065 00001B29 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3066                              <1> DC0:
  3067 00001B2B E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3068 00001B30 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3069                              <1> 
  3070 00001B32 C605[2C6E0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3071                              <1> 
  3072 00001B39 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3073 00001B3E E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3074                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3075                              <1> 	; 05/12/2021
  3076 00001B43 89F3                <1> 	mov	ebx, esi
  3077 00001B45 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3078 00001B47 C3                  <1> 	RETn
  3079                              <1> DC_NON:
  3080 00001B48 800D[2C6E0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3081 00001B4F EBE8                <1> 	JMP	SHORT FINIS
  3082                              <1> 
  3083                              <1> ;-------------------------------------------------------------------------------
  3084                              <1> ; FORMAT_SET	(AH = 17H)
  3085                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3086                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3087                              <1> ;
  3088                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3089                              <1> ;		DI     = DRIVE #
  3090                              <1> ;
  3091                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3092                              <1> ;		AH = @DSKETTE_STATUS
  3093                              <1> ;		CY = 1 IF ERROR
  3094                              <1> ;-------------------------------------------------------------------------------
  3095                              <1> FORMAT_SET:
  3096 00001B51 E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3097                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3098                              <1> 	; 05/12/2021
  3099 00001B56 56                  <1> 	push	esi
  3100 00001B57 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3101 00001B5A 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3102 00001B5C 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3103 00001B5F 80A7[396E0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3104 00001B66 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3105 00001B68 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3106 00001B6A 808F[396E0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3107 00001B71 EB48                <1> 	JMP	SHORT S0
  3108                              <1> NOT_320:
  3109 00001B73 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3110 00001B78 803D[2C6E0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3111 00001B7F 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3112                              <1> S3:
  3113 00001B81 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3114 00001B83 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3115 00001B85 808F[396E0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3116 00001B8C EB2D                <1> 	JMP	SHORT S0
  3117                              <1> NOT_320_12:
  3118 00001B8E 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3119 00001B90 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3120 00001B92 808F[396E0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3121 00001B99 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3122                              <1> NOT_12:	
  3123 00001B9B 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3124 00001B9D 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3125                              <1> 
  3126 00001B9F F687[396E0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3127 00001BA6 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3128 00001BA8 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3129 00001BAA F687[396E0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3130 00001BB1 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3131                              <1> ASSUME:
  3132 00001BB3 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3133                              <1> OR_IT_IN:
  3134 00001BB5 0887[396E0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3135                              <1> S0:
  3136 00001BBB E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3137 00001BC0 E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3138                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3139                              <1> 	; 05/12/2021
  3140 00001BC5 5B                  <1> 	pop	ebx
  3141 00001BC6 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3142 00001BC8 C3                  <1> 	RETn
  3143                              <1> FS_ERR:
  3144 00001BC9 C605[2C6E0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3145 00001BD0 EBE9                <1> 	JMP	SHORT S0
  3146                              <1> 
  3147                              <1> ;-------------------------------------------------------------------------------
  3148                              <1> ; SET_MEDIA	(AH = 18H)
  3149                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3150                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3151                              <1> ;
  3152                              <1> ; ON ENTRY:
  3153                              <1> ;	[BP]	= SECTOR PER TRACK
  3154                              <1> ;	[BP+1]	= TRACK #
  3155                              <1> ;	DI	= DRIVE #
  3156                              <1> ;
  3157                              <1> ; ON EXIT:
  3158                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3159                              <1> ;	IF NO ERROR:
  3160                              <1> ;		AH = 0
  3161                              <1> ;		CY = 0
  3162                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3163                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3164                              <1> ;	IF ERROR:	
  3165                              <1> ;		AH = @DSKETTE_STATUS
  3166                              <1> ;		CY = 1
  3167                              <1> ;-------------------------------------------------------------------------------
  3168                              <1> SET_MEDIA:
  3169 00001BD2 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3170 00001BD7 F687[396E0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3171 00001BDE 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3172 00001BE0 E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3173 00001BE5 803D[2C6E0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3174 00001BEC 746B                <1> 	JE	short SM_RTN
  3175 00001BEE C605[2C6E0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3176                              <1> SM_CMOS:
  3177 00001BF5 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3178                              <1> 	;;20/02/2015
  3179                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3180                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3181 00001BFA 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3182 00001BFC E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3183 00001C01 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3184 00001C03 57                  <1> 	PUSH	eDI			; SAVE REG.
  3185 00001C04 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3186 00001C06 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3187                              <1> DR_SEARCH:
  3188 00001C0B 8AA3[1C680000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3189 00001C11 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3190 00001C14 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3191 00001C16 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3192                              <1> DR_FND:
  3193 00001C18 8BBB[1D680000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3194                              <1> MD_SEARCH:
  3195 00001C1E 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3196 00001C21 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3197 00001C24 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3198 00001C26 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3199 00001C29 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3200 00001C2C 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3201                              <1> NXT_MD:
  3202                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3203 00001C2E 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3204 00001C31 E2D8                <1> 	LOOP    DR_SEARCH
  3205 00001C33 5F                  <1> 	POP	eDI			; RESTORE REG.
  3206                              <1> MD_NOT_FND:
  3207 00001C34 C605[2C6E0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3208 00001C3B EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3209                              <1> MD_FND:
  3210 00001C3D 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3211 00001C40 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3212 00001C42 7502                <1> 	JNE	short MD_SET
  3213 00001C44 0C20                <1> 	OR	AL,DBL_STEP
  3214                              <1> MD_SET:
  3215                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3216 00001C46 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3217 00001C49 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3218 00001C4B 5F                  <1> 	POP	eDI
  3219 00001C4C 80A7[396E0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3220 00001C53 0887[396E0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3221                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3222                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3223                              <1> SM_RTN:
  3224 00001C59 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3225 00001C5E E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3226 00001C63 C3                  <1> 	RETn
  3227                              <1> 
  3228                              <1> ;----------------------------------------------------------------
  3229                              <1> ; DR_TYPE_CHECK							:
  3230                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3231                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3232                              <1> ; ON ENTRY:							:
  3233                              <1> ;	AL = DRIVE TYPE						:
  3234                              <1> ; ON EXIT:							:
  3235                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3236                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3237                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3238                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3239                              <1> ; REGISTERS ALTERED: eBX						:
  3240                              <1> ;----------------------------------------------------------------		
  3241                              <1> DR_TYPE_CHECK:
  3242                              <1> 	;PUSH	AX			
  3243                              <1> 	; 05/12/2021
  3244 00001C64 50                  <1> 	push	eax
  3245 00001C65 51                  <1> 	PUSH	eCX
  3246 00001C66 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3247 00001C68 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3248                              <1> TYPE_CHK:	
  3249 00001C6D 8AA3[1C680000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3250 00001C73 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3251 00001C75 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3252                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3253 00001C77 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3254 00001C7A E2F1                <1> 	LOOP    TYPE_CHK
  3255                              <1> 	;
  3256 00001C7C BB[7B680000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3257                              <1> 					; Default for GET_PARM (11/12/2014)
  3258                              <1> 	;
  3259 00001C81 F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3260 00001C82 EB06                <1> 	JMP	SHORT TYPE_RTN
  3261                              <1> DR_TYPE_VALID:
  3262 00001C84 8B9B[1D680000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3263                              <1> TYPE_RTN:
  3264 00001C8A 59                  <1> 	POP	eCX
  3265                              <1> 	;POP	AX
  3266                              <1> 	; 05/12/2021
  3267 00001C8B 58                  <1> 	pop	eax
  3268 00001C8C C3                  <1> 	RETn	
  3269                              <1> 		
  3270                              <1> ;----------------------------------------------------------------
  3271                              <1> ; SEND_SPEC							:
  3272                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3273                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3274                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3275                              <1> ; ON EXIT:	NONE						:	
  3276                              <1> ; REGISTERS ALTERED: CX, DX					:
  3277                              <1> ;----------------------------------------------------------------		
  3278                              <1> SEND_SPEC:
  3279 00001C8D 50                  <1> 	PUSH	eAX			; SAVE AX
  3280 00001C8E B8[B41C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3281 00001C93 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3282 00001C94 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3283 00001C96 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3284 00001C9B 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3285 00001C9D E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3286 00001CA2 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3287 00001CA7 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3288 00001CA9 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3289 00001CAE E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3290 00001CB3 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3291                              <1> SPECBAC:
  3292 00001CB4 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3293 00001CB5 C3                  <1> 	RETn
  3294                              <1> 
  3295                              <1> ;----------------------------------------------------------------
  3296                              <1> ; SEND_SPEC_MD							:
  3297                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3298                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3299                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3300                              <1> ; ON EXIT:	NONE						:	
  3301                              <1> ; REGISTERS ALTERED: AX						:
  3302                              <1> ;----------------------------------------------------------------		
  3303                              <1> SEND_SPEC_MD:
  3304 00001CB6 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3305 00001CB7 B8[D41C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3306 00001CBC 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3307 00001CBD B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3308 00001CBF E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3309 00001CC4 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3310 00001CC6 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3311 00001CCB 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3312 00001CCE E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3313 00001CD3 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3314                              <1> SPEC_ESBAC:
  3315 00001CD4 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3316 00001CD5 C3                  <1> 	RETn
  3317                              <1> 
  3318                              <1> ;-------------------------------------------------------------------------------
  3319                              <1> ; XLAT_NEW  
  3320                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3321                              <1> ;	MODE TO NEW ARCHITECTURE.
  3322                              <1> ;
  3323                              <1> ; ON ENTRY:	DI = DRIVE #
  3324                              <1> ;-------------------------------------------------------------------------------
  3325                              <1> XLAT_NEW:
  3326 00001CD6 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3327 00001CD9 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3328 00001CDB 80BF[396E0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3329 00001CE2 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3330 00001CE4 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3331 00001CE7 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3332 00001CEA A0[386E0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3333 00001CEF D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3334 00001CF1 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3335 00001CF3 80A7[396E0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3336 00001CFA 0887[396E0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3337                              <1> XN_OUT:
  3338 00001D00 C3                  <1> 	RETn
  3339                              <1> DO_DET:
  3340 00001D01 E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3341 00001D06 C3                  <1> 	RETn
  3342                              <1> 
  3343                              <1> ;-------------------------------------------------------------------------------
  3344                              <1> ; XLAT_OLD 
  3345                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3346                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3347                              <1> ;
  3348                              <1> ; ON ENTRY:	DI = DRIVE
  3349                              <1> ;-------------------------------------------------------------------------------
  3350                              <1> XLAT_OLD:
  3351 00001D07 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3352                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3353                              <1>         ;ja	XO_OUT
  3354                              <1>         ; 05/12/2021
  3355 00001D0A 77F4                <1> 	ja	short XN_OUT
  3356 00001D0C 80BF[396E0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3357 00001D13 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3358                              <1> 
  3359                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3360                              <1> 
  3361 00001D15 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3362 00001D18 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3363 00001D1B B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3364 00001D1D D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3365 00001D1F 8425[386E0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3366 00001D25 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3367                              <1> 
  3368                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3369                              <1> 
  3370 00001D27 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3371 00001D29 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3372 00001D2B F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3373 00001D2D 2025[386E0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3374                              <1> 
  3375                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3376                              <1> 
  3377 00001D33 8A87[396E0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3378 00001D39 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3379 00001D3B D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3380 00001D3D 0805[386E0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3381                              <1> 
  3382                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3383                              <1> 
  3384                              <1> SAVE_SET:
  3385 00001D43 8AA7[396E0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3386 00001D49 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3387 00001D4B 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3388 00001D4E 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3389 00001D51 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3390 00001D53 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3391 00001D55 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3392 00001D58 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3393 00001D5A F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3394 00001D5D 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3395                              <1> UNKNO:
  3396 00001D5F B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3397 00001D61 EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3398                              <1> CHK_144:
  3399 00001D63 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3400                              <1> 	;;20/02/2015
  3401                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3402 00001D68 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3403 00001D6A 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3404 00001D6C 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3405 00001D6E B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3406 00001D70 EB0C                <1> 	JMP	SHORT TST_DET
  3407                              <1> CHK_250:
  3408 00001D72 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3409 00001D74 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3410 00001D77 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3411 00001D79 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3412 00001D7C 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3413                              <1> TST_DET:
  3414 00001D7E F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3415 00001D81 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3416 00001D83 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3417                              <1> AL_SET:
  3418 00001D85 80A7[396E0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3419 00001D8C 0887[396E0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3420                              <1> XO_OUT:
  3421 00001D92 C3                  <1> 	RETn
  3422                              <1> 
  3423                              <1> ;-------------------------------------------------------------------------------
  3424                              <1> ; RD_WR_VF
  3425                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3426                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3427                              <1> ;
  3428                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3429                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3430                              <1> ;
  3431                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3432                              <1> ;-------------------------------------------------------------------------------
  3433                              <1> RD_WR_VF:
  3434                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3435 00001D93 50                  <1> 	push	eax ; 05/12/2021
  3436 00001D94 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3437 00001D99 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3438                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3439 00001D9E 58                  <1> 	pop	eax ; 05/12/2021
  3440                              <1> DO_AGAIN:
  3441                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3442 00001D9F 50                  <1> 	push	eax ; 05/12/2021
  3443 00001DA0 E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3444                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3445 00001DA5 58                  <1> 	pop	eax ; 05/12/2021
  3446                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3447                              <1> 	; 05/12/2021
  3448 00001DA6 7305                <1> 	jnc	short RWV
  3449 00001DA8 E9C3000000          <1> 	jmp	RWV_END
  3450                              <1> RWV:
  3451                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3452 00001DAD 50                  <1> 	push	eax ; 05/12/2021
  3453 00001DAE 8AB7[396E0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3454 00001DB4 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3455 00001DB7 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3456                              <1> 	;;20/02/2015
  3457                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3458 00001DBC 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3459 00001DBE 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3460 00001DC0 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3461 00001DC2 F687[396E0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3462 00001DC9 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3463 00001DCB B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3464 00001DCD EB0F                <1> 	JMP	SHORT RWV_2
  3465                              <1> RWV_1:
  3466 00001DCF 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3467 00001DD1 F687[396E0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3468 00001DD8 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3469 00001DDA B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3470 00001DDC EB04                <1> 	jmp	short rwv_3
  3471                              <1> RWV_2:
  3472 00001DDE 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3473 00001DE0 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3474                              <1> rwv_3:
  3475 00001DE2 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3476 00001DE7 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3477                              <1> 
  3478                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3479                              <1> 
  3480 00001DE9 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3481 00001DEA 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3482 00001DEC B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3483                              <1> RWV_DR_SEARCH:
  3484 00001DF1 8AA3[1C680000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3485 00001DF7 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3486 00001DFA 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3487 00001DFC 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3488                              <1> RWV_DR_FND:
  3489 00001DFE 8BBB[1D680000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3490                              <1> RWV_MD_SEARH:
  3491 00001E04 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3492 00001E07 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3493                              <1> RWV_NXT_MD:
  3494                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3495 00001E09 83C305              <1> 	add	eBX, 5
  3496 00001E0C E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3497 00001E0E 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3498                              <1> 
  3499                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3500                              <1> 
  3501                              <1> RWV_ASSUME:
  3502 00001E0F BB[3A680000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3503 00001E14 F687[396E0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3504 00001E1B 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3505 00001E1D BB[54680000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3506 00001E22 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3507                              <1> 
  3508                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3509                              <1> 	 			
  3510                              <1> RWV_MD_FND:
  3511 00001E24 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3512 00001E26 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3513                              <1> 	
  3514                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3515                              <1> 
  3516                              <1> RWV_MD_FND1:
  3517 00001E27 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3518 00001E2C E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3519 00001E31 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3520 00001E33 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3521                              <1> RWV_DBL:
  3522 00001E38 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3523 00001E39 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3524 00001E3E 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3525 00001E3F 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3526                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3527 00001E41 58                  <1> 	pop	eax ; 05/12/2021
  3528                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3529 00001E42 50                  <1> 	push	eax ; 05/12/2021
  3530 00001E43 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3531 00001E44 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3532 00001E49 5B                  <1> 	POP	eBX 
  3533                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3534 00001E4A 58                  <1> 	pop	eax ; 05/12/2021
  3535 00001E4B 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3536                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3537 00001E4D 50                  <1> 	push	eax ; 05/12/2021
  3538 00001E4E 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3539 00001E4F E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3540 00001E54 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3541 00001E55 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3542 00001E57 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3543 00001E5C 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3544 00001E5E E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3545                              <1> CHK_RET:
  3546 00001E63 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3547                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3548 00001E68 58                  <1> 	pop	eax ; 05/12/2021
  3549 00001E69 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3550 00001E6B E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3551                              <1> RWV_END:
  3552 00001E70 E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3553 00001E75 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3554                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3555                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3556 00001E7A 50                  <1> 	push	eax ; 05/12/2021
  3557 00001E7B E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3558                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3559 00001E80 58                  <1> 	pop	eax ; 05/12/2021
  3560 00001E81 E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3561 00001E86 C3                  <1> 	RETn
  3562                              <1> 
  3563                              <1> ;-------------------------------------------------------------------------------
  3564                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3565                              <1> ;-------------------------------------------------------------------------------
  3566                              <1> SETUP_STATE:
  3567 00001E87 F687[396E0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3568 00001E8E 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3569 00001E90 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3570 00001E94 F687[396E0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3571 00001E9B 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3572 00001E9D F687[396E0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3573 00001EA4 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3574 00001EA6 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3575                              <1> AX_SET:	
  3576 00001EAA 80A7[396E0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3577 00001EB1 08A7[396E0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3578 00001EB7 8025[346E0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3579 00001EBE C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3580 00001EC1 0805[346E0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3581                              <1> J1C:	
  3582 00001EC7 C3                  <1> 	RETn
  3583                              <1> 
  3584                              <1> ;-------------------------------------------------------------------------------
  3585                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3586                              <1> ;-------------------------------------------------------------------------------
  3587                              <1> FMT_INIT:
  3588 00001EC8 F687[396E0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3589 00001ECF 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3590 00001ED1 E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3591                              <1> 	;; 20/02/2015
  3592                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3593 00001ED6 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3594 00001ED8 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3595                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3596 00001EDA 8AA7[396E0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3597 00001EE0 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3598 00001EE3 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3599 00001EE5 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3600 00001EE7 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3601 00001EEA EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3602                              <1> N_360:	
  3603 00001EEC FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3604 00001EEE 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3605                              <1> F1_RATE:
  3606 00001EF0 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3607 00001EF3 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3608                              <1> N_12:	
  3609 00001EF5 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3610 00001EF7 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3611 00001EF9 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3612 00001EFC 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3613 00001EFE F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3614 00001F01 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3615 00001F03 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3616 00001F06 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3617                              <1> N_720:
  3618 00001F08 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3619 00001F0A 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3620 00001F0C EBE2                <1> 	JMP	SHORT F1_RATE
  3621                              <1> ISNT_12: 
  3622 00001F0E 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3623                              <1> 
  3624                              <1> SKP_STATE:
  3625 00001F11 88A7[396E0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3626                              <1> F1_OUT:
  3627 00001F17 C3                  <1> 	RETn
  3628                              <1> CL_DRV:	
  3629 00001F18 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3630 00001F1A EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3631                              <1> 
  3632                              <1> ;-------------------------------------------------------------------------------
  3633                              <1> ; MED_CHANGE	
  3634                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3635                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3636                              <1> ;
  3637                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3638                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3639                              <1> ;-------------------------------------------------------------------------------
  3640                              <1> MED_CHANGE:
  3641 00001F1C E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3642 00001F21 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3643 00001F23 80A7[396E0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3644                              <1> 
  3645                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3646                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3647                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3648                              <1> 
  3649 00001F2A 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3650 00001F2D B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3651 00001F2F D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3652 00001F31 F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3653 00001F33 FA                  <1> 	CLI				; NO INTERRUPTS
  3654 00001F34 2005[2A6E0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3655 00001F3A FB                  <1> 	STI				; INTERRUPTS ENABLED
  3656 00001F3B E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3657                              <1> 
  3658                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3659                              <1> 
  3660 00001F40 E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3661 00001F45 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3662 00001F47 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3663 00001F4C 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3664 00001F4E E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3665 00001F53 C605[2C6E0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3666                              <1> OK1:
  3667 00001F5A E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3668 00001F5F 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3669                              <1> OK4:
  3670 00001F61 C605[2C6E0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3671                              <1> OK2:		
  3672 00001F68 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3673 00001F69 C3                  <1> 	RETn
  3674                              <1> MC_OUT:
  3675 00001F6A F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3676 00001F6B C3                  <1> 	RETn
  3677                              <1> 
  3678                              <1> ;-------------------------------------------------------------------------------
  3679                              <1> ; SEND_RATE
  3680                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3681                              <1> ; ON ENTRY:	DI = DRIVE #
  3682                              <1> ; ON EXIT:	NONE
  3683                              <1> ; REGISTERS ALTERED: DX
  3684                              <1> ;-------------------------------------------------------------------------------
  3685                              <1> SEND_RATE:
  3686                              <1> 	;PUSH	AX			; SAVE REG.
  3687                              <1> 	; 05/12/2021
  3688 00001F6C 50                  <1> 	push	eax
  3689 00001F6D 8025[346E0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3690 00001F74 8A87[396E0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3691 00001F7A 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3692 00001F7C 0805[346E0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3693 00001F82 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3694 00001F85 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3695 00001F89 EE                  <1> 	OUT	DX,AL
  3696                              <1> 	;POP	AX			; RESTORE REG.
  3697                              <1> 	; 05/12/2021
  3698 00001F8A 58                  <1> 	pop	eax
  3699 00001F8B C3                  <1> 	RETn
  3700                              <1> 
  3701                              <1> ;-------------------------------------------------------------------------------
  3702                              <1> ; CHK_LASTRATE
  3703                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3704                              <1> ; ON ENTRY:
  3705                              <1> ;	DI = DRIVE #
  3706                              <1> ; ON EXIT:
  3707                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3708                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3709                              <1> ; REGISTERS ALTERED: DX
  3710                              <1> ;-------------------------------------------------------------------------------
  3711                              <1> CHK_LASTRATE:
  3712                              <1> 	;PUSH	AX			; SAVE REG.
  3713                              <1> 	; 05/12/2021
  3714 00001F8C 50                  <1> 	push	eax
  3715 00001F8D 2225[346E0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3716 00001F93 8A87[396E0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3717 00001F99 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3718 00001F9D 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3719                              <1> 					; ZF = 1 RATE IS THE SAME
  3720                              <1> 	;POP	AX			; RESTORE REG.
  3721                              <1> 	; 05/12/2021
  3722 00001F9F 58                  <1> 	pop	eax
  3723 00001FA0 C3                  <1> 	RETn
  3724                              <1> 
  3725                              <1> ;-------------------------------------------------------------------------------
  3726                              <1> ; DMA_SETUP
  3727                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3728                              <1> ;
  3729                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3730                              <1> ;
  3731                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3732                              <1> ;-------------------------------------------------------------------------------
  3733                              <1> 
  3734                              <1> ; SI = Head #, # of Sectors or DASD Type
  3735                              <1> 
  3736                              <1> ; 22/08/2015
  3737                              <1> ; 08/02/2015 - Protected Mode Modification
  3738                              <1> ; 06/02/2015 - 07/02/2015
  3739                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3740                              <1> ; (DMA Addres = Physical Address)
  3741                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3742                              <1> ;
  3743                              <1> ; 04/02/2016 (clc)
  3744                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3745                              <1> ; 16/12/2014 (IODELAY)
  3746                              <1> 
  3747                              <1> DMA_SETUP:
  3748                              <1> 
  3749                              <1> ;; 20/02/2015
  3750 00001FA1 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3751 00001FA4 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3752 00001FAA 7569                <1> 	jnz	short dma_bnd_err_stc
  3753                              <1> 	;
  3754                              <1> 	;push	ax			; DMA command
  3755                              <1> 	; 05/12/2021
  3756 00001FAC 50                  <1> 	push	eax
  3757 00001FAD 52                  <1> 	push	edx			; *
  3758 00001FAE B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3759 00001FB0 E840030000          <1> 	call	GET_PARM		; 
  3760 00001FB5 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3761                              <1> 	;mov	ax, si			; Sector count
  3762                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3763                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3764                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3765                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3766                              <1> 	; 05/12/2021
  3767 00001FB7 89F2                <1> 	mov	edx, esi
  3768 00001FB9 29C0                <1> 	sub	eax, eax
  3769 00001FBB 88D4                <1> 	mov	ah, dl
  3770 00001FBD D1E8                <1> 	shr	eax, 1
  3771 00001FBF D3E0                <1> 	shl	eax, cl
  3772                              <1> 	;
  3773 00001FC1 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3774 00001FC3 6689C1              <1> 	mov	cx, ax
  3775 00001FC6 5A                  <1> 	pop	edx			; *
  3776                              <1> 	;pop	ax
  3777                              <1> 	; 05/12/2021
  3778 00001FC7 58                  <1> 	pop	eax
  3779 00001FC8 3C42                <1> 	cmp	al, 42h
  3780 00001FCA 7507                <1>         jne     short NOT_VERF
  3781 00001FCC BA0000FF00          <1> 	mov	edx, 0FF0000h
  3782 00001FD1 EB08                <1> 	jmp	short J33
  3783                              <1> NOT_VERF:
  3784 00001FD3 6601CA              <1> 	add	dx, cx			; check for overflow
  3785 00001FD6 723E                <1> 	jc	short dma_bnd_err
  3786                              <1> 	;
  3787 00001FD8 6629CA              <1> 	sub	dx, cx			; Restore start address
  3788                              <1> J33:
  3789 00001FDB FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3790 00001FDC E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3791                              <1> 	IODELAY				; WAIT FOR I/O
  2133 00001FDE EB00                <2>  jmp short $+2
  2134 00001FE0 EB00                <2>  jmp short $+2
  3792 00001FE2 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3793 00001FE4 89D0                <1> 	mov	eax,edx			; Buffer address
  3794 00001FE6 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3795                              <1> 	IODELAY				; WAIT FOR I/O
  2133 00001FE8 EB00                <2>  jmp short $+2
  2134 00001FEA EB00                <2>  jmp short $+2
  3796 00001FEC 88E0                <1> 	MOV	AL,AH
  3797 00001FEE E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3798 00001FF0 C1E810              <1> 	shr	eax,16
  3799                              <1> 	IODELAY				; I/O WAIT STATE
  2133 00001FF3 EB00                <2>  jmp short $+2
  2134 00001FF5 EB00                <2>  jmp short $+2
  3800 00001FF7 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3801                              <1> 	IODELAY
  2133 00001FF9 EB00                <2>  jmp short $+2
  2134 00001FFB EB00                <2>  jmp short $+2
  3802 00001FFD 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3803 00002000 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3804                              <1> 	IODELAY				; WAIT FOR I/O
  2133 00002002 EB00                <2>  jmp short $+2
  2134 00002004 EB00                <2>  jmp short $+2
  3805 00002006 88E0                <1> 	MOV	AL,AH
  3806 00002008 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3807                              <1> 	IODELAY
  2133 0000200A EB00                <2>  jmp short $+2
  2134 0000200C EB00                <2>  jmp short $+2
  3808 0000200E FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3809 0000200F B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3810 00002011 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3811                              <1> 
  3812 00002013 F8                  <1> 	clc	; 04/02/2016
  3813 00002014 C3                  <1> 	retn
  3814                              <1> 
  3815                              <1> dma_bnd_err_stc:
  3816 00002015 F9                  <1> 	stc
  3817                              <1> dma_bnd_err:
  3818 00002016 C605[2C6E0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3819 0000201D C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3820                              <1> 
  3821                              <1> ;; 16/12/2014
  3822                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3823                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3824                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3825                              <1> ;;	IODELAY
  3826                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3827                              <1> ;;	;SIODELAY
  3828                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3829                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3830                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3831                              <1> ;;      ;JMP	SHORT J33
  3832                              <1> ;;;NOT_VERF:	
  3833                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3834                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3835                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3836                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3837                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3838                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3839                              <1> ;;	;JNC	short J33
  3840                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3841                              <1> ;;;J33:
  3842                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3843                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3844                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3845                              <1> ;;	IODELAY
  3846                              <1> ;;	MOV	AL,AH
  3847                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3848                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3849                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3850                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3851                              <1> ;;	IODELAY
  3852                              <1> ;;	;AND	AL,00001111B
  3853                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3854                              <1> ;;	;SIODELAY
  3855                              <1> ;;
  3856                              <1> ;;;----- DETERMINE COUNT
  3857                              <1> ;;	sub	eax, eax ; 08/02/2015
  3858                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3859                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3860                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3861                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3862                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3863                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3864                              <1> ;;	CALL	GET_PARM		; "
  3865                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3866                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3867                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3868                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3869                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3870                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3871                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3872                              <1> ;;	IODELAY
  3873                              <1> ;;	MOV	AL, AH
  3874                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3875                              <1> ;;	;IODELAY
  3876                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3877                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3878                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3879                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3880                              <1> ;;	add	ecx, eax ; 08/02/2015
  3881                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3882                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3883                              <1> ;;	SIODELAY
  3884                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3885                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3886                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3887                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3888                              <1> ;;	jz	short NO_BAD
  3889                              <1> ;;dma_bnd_err:
  3890                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3891                              <1> ;;NO_BAD:
  3892                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3893                              <1> 
  3894                              <1> ;-------------------------------------------------------------------------------
  3895                              <1> ; FMTDMA_SET
  3896                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3897                              <1> ;
  3898                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3899                              <1> ;
  3900                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3901                              <1> ;-------------------------------------------------------------------------------
  3902                              <1> 
  3903                              <1> 	; 05/12/2021
  3904                              <1> FMTDMA_SET:
  3905                              <1> ;; 20/02/2015 modification	
  3906 0000201E 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3907 00002021 F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3908 00002027 75EC                <1> 	jnz	short dma_bnd_err_stc
  3909                              <1> 	;
  3910                              <1> 	;push	dx			; *
  3911                              <1> 	; 05/12/2021
  3912 00002029 52                  <1> 	push	edx
  3913 0000202A B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3914 0000202C E8C4020000          <1> 	call	GET_PARM		; "
  3915                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3916                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3917                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3918                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3919                              <1> 	;mov	cx, ax
  3920                              <1> 	; 05/12/2021
  3921 00002031 29C9                <1> 	sub	ecx, ecx
  3922 00002033 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3923 00002035 D1E1                <1> 	shl	ecx, 1
  3924 00002037 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3925 00002039 6649                <1> 	dec	cx
  3926                              <1> 	;pop	dx			; *
  3927                              <1> 	; 05/12/2021
  3928 0000203B 5A                  <1> 	pop	edx
  3929 0000203C 6601CA              <1> 	add	dx, cx			; check for overflow
  3930 0000203F 72D5                <1> 	jc	short dma_bnd_err
  3931                              <1> 	;
  3932 00002041 6629CA              <1> 	sub	dx, cx			; Restore start address
  3933                              <1> 	;
  3934 00002044 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3935 00002046 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3936 00002047 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3937                              <1> 	IODELAY				; WAIT FOR I/O
  2133 00002049 EB00                <2>  jmp short $+2
  2134 0000204B EB00                <2>  jmp short $+2
  3938 0000204D E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3939 0000204F 89D0                <1> 	mov	eax,edx			; Buffer address
  3940 00002051 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3941                              <1> 	IODELAY				; WAIT FOR I/O
  2133 00002053 EB00                <2>  jmp short $+2
  2134 00002055 EB00                <2>  jmp short $+2
  3942 00002057 88E0                <1> 	MOV	AL,AH
  3943 00002059 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3944 0000205B C1E810              <1> 	shr	eax,16
  3945                              <1> 	IODELAY				; I/O WAIT STATE
  2133 0000205E EB00                <2>  jmp short $+2
  2134 00002060 EB00                <2>  jmp short $+2
  3946 00002062 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3947                              <1> 	IODELAY
  2133 00002064 EB00                <2>  jmp short $+2
  2134 00002066 EB00                <2>  jmp short $+2
  3948 00002068 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3949 0000206B E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3950                              <1> 	IODELAY				; WAIT FOR I/O
  2133 0000206D EB00                <2>  jmp short $+2
  2134 0000206F EB00                <2>  jmp short $+2
  3951 00002071 88E0                <1> 	MOV	AL,AH
  3952 00002073 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3953                              <1> 	IODELAY
  2133 00002075 EB00                <2>  jmp short $+2
  2134 00002077 EB00                <2>  jmp short $+2
  3954 00002079 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3955 0000207A B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3956 0000207C E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3957 0000207E C3                  <1> 	retn
  3958                              <1> 
  3959                              <1> ;; 08/02/2015 - Protected Mode Modification
  3960                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3961                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3962                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3963                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3964                              <1> ;;	IODELAY
  3965                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3966                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3967                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3968                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3969                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3970                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3971                              <1> ;;	;JNC	short J33A
  3972                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3973                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3974                              <1> ;;;J33A:
  3975                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3976                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3977                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3978                              <1> ;;	IODELAY
  3979                              <1> ;;	MOV	AL,AH
  3980                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3981                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3982                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3983                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3984                              <1> ;;	IODELAY
  3985                              <1> ;;	;AND	AL,00001111B
  3986                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3987                              <1> ;;
  3988                              <1> ;;;----- DETERMINE COUNT
  3989                              <1> ;;	sub	eax, eax ; 08/02/2015
  3990                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3991                              <1> ;;	CALL	GET_PARM		; "
  3992                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3993                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3994                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3995                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3996                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3997                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3998                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3999                              <1> ;;	IODELAY
  4000                              <1> ;;	MOV	AL, AH
  4001                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  4002                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  4003                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  4004                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  4005                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  4006                              <1> ;;	add	ecx, eax ; 08/02/2015
  4007                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  4008                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4009                              <1> ;;	SIODELAY
  4010                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  4011                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  4012                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  4013                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  4014                              <1> ;;	jz	short FMTDMA_OK
  4015                              <1> ;;	stc	; 20/02/2015
  4016                              <1> ;;fmtdma_bnd_err:
  4017                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  4018                              <1> ;;FMTDMA_OK:
  4019                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  4020                              <1> 
  4021                              <1> ;-------------------------------------------------------------------------------
  4022                              <1> ; NEC_INIT	
  4023                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  4024                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  4025                              <1> ;
  4026                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  4027                              <1> ;
  4028                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4029                              <1> ;-------------------------------------------------------------------------------
  4030                              <1> NEC_INIT:
  4031                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4032                              <1> 	; 05/12/2021
  4033 0000207F 50                  <1> 	push	eax
  4034 00002080 E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4035                              <1> 
  4036                              <1> ;-----	DO THE SEEK OPERATION
  4037                              <1> 
  4038 00002085 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4039 00002088 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4040                              <1> 	;POP	AX			; RECOVER COMMAND
  4041                              <1> 	; 05/12/2021
  4042 0000208D 58                  <1> 	pop	eax
  4043 0000208E 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4044 00002090 BB[AE200000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4045 00002095 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4046                              <1> 
  4047                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4048                              <1> 
  4049 00002096 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4050 0000209B 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4051 0000209E 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4052 000020A0 C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4053 000020A3 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4054 000020A6 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4055 000020A8 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4056 000020AD 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4057                              <1> ER_1:
  4058 000020AE C3                  <1> 	RETn
  4059                              <1> 
  4060                              <1> ;-------------------------------------------------------------------------------
  4061                              <1> ; RWV_COM
  4062                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4063                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4064                              <1> ;
  4065                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4066                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4067                              <1> ;-------------------------------------------------------------------------------
  4068                              <1> RWV_COM:
  4069 000020AF B8[FA200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4070 000020B4 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4071 000020B5 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4072 000020B8 E83E030000          <1> 	CALL	NEC_OUTPUT
  4073 000020BD 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4074 000020C0 E836030000          <1> 	CALL	NEC_OUTPUT
  4075 000020C5 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4076 000020C8 E82E030000          <1> 	CALL	NEC_OUTPUT
  4077 000020CD B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4078 000020CF E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4079 000020D4 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4080 000020D9 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4081 000020DB E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4082 000020E0 E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4083 000020E5 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4084                              <1> _R15:
  4085 000020E8 E80E030000          <1> 	CALL	NEC_OUTPUT
  4086 000020ED B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4087 000020EF E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4088 000020F4 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4089 000020F9 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4090                              <1> ER_2:
  4091 000020FA C3                  <1> 	RETn
  4092                              <1> 
  4093                              <1> ;-------------------------------------------------------------------------------
  4094                              <1> ; NEC_TERM
  4095                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4096                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4097                              <1> ;
  4098                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4099                              <1> ;-------------------------------------------------------------------------------
  4100                              <1> NEC_TERM:
  4101                              <1> 
  4102                              <1> ;-----	LET THE OPERATION HAPPEN
  4103                              <1> 
  4104 000020FB 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4105 000020FC E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4106 00002101 9C                  <1> 	PUSHFd	; 05/12/2021
  4107 00002102 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4108 00002107 724B                <1> 	JC	short SET_END_POP
  4109 00002109 9D                  <1> 	POPFd	; 05/12/2021
  4110 0000210A 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4111                              <1> 
  4112                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4113                              <1> 
  4114 0000210C FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4115 0000210D BE[2D6E0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4116 00002112 AC                  <1> 	lodsb				; GET ST0
  4117 00002113 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4118 00002115 7433                <1> 	JZ	short SET_END
  4119 00002117 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4120 00002119 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4121                              <1> 
  4122                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4123                              <1> 
  4124 0000211B AC                  <1> 	lodsb				; GET ST1
  4125 0000211C D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4126 0000211E B404                <1> 	MOV	AH,RECORD_NOT_FND
  4127 00002120 7222                <1> 	JC	short J19
  4128 00002122 C0E002              <1> 	SAL	AL,2
  4129 00002125 B410                <1> 	MOV	AH,BAD_CRC
  4130 00002127 721B                <1> 	JC	short J19
  4131 00002129 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4132 0000212B B408                <1> 	MOV	AH,BAD_DMA
  4133 0000212D 7215                <1> 	JC	short J19
  4134 0000212F C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4135 00002132 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4136 00002134 720E                <1> 	JC	short J19
  4137 00002136 D0E0                <1> 	SAL	AL,1
  4138 00002138 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4139 0000213A 7208                <1> 	JC	short J19
  4140 0000213C D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4141 0000213E B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4142 00002140 7202                <1> 	JC	short J19
  4143                              <1> 
  4144                              <1> ;----- 	NEC MUST HAVE FAILED
  4145                              <1> J18:
  4146 00002142 B420                <1> 	MOV	AH,BAD_NEC
  4147                              <1> J19:
  4148 00002144 0825[2C6E0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4149                              <1> SET_END:
  4150 0000214A 803D[2C6E0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4151 00002151 F5                  <1> 	CMC
  4152 00002152 5E                  <1> 	POP	eSI
  4153 00002153 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4154                              <1> 
  4155                              <1> SET_END_POP:
  4156 00002154 9D                  <1> 	POPFd	; 05/12/2021
  4157 00002155 EBF3                <1> 	JMP	SHORT SET_END
  4158                              <1> 
  4159                              <1> ;-------------------------------------------------------------------------------
  4160                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4161                              <1> ;-------------------------------------------------------------------------------
  4162                              <1> DSTATE:
  4163 00002157 803D[2C6E0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4164 0000215E 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4165 00002160 808F[396E0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4166 00002167 F687[396E0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4167 0000216E 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4168 00002170 8A87[396E0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4169 00002176 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4170 00002178 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4171 0000217A 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4172                              <1> 
  4173                              <1> ;----- 	CHECK IF IT IS 1.44M
  4174                              <1> 
  4175 0000217C E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4176                              <1> 	;;20/02/2015
  4177                              <1> 	;;JC	short M_12		; CMOS BAD
  4178 00002181 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4179 00002183 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4180 00002185 7410                <1> 	JE	short M_12		; YES
  4181                              <1> M_720:
  4182 00002187 80A7[396E0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4183 0000218E 808F[396E0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4184 00002195 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4185                              <1> M_12:	
  4186 00002197 808F[396E0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4187                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4188                              <1> SETBAC:
  4189 0000219E C3                  <1> 	RETn
  4190                              <1> 
  4191                              <1> ;-------------------------------------------------------------------------------
  4192                              <1> ; RETRY	
  4193                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4194                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4195                              <1> ;
  4196                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4197                              <1> ;-------------------------------------------------------------------------------
  4198                              <1> RETRY:
  4199 0000219F 803D[2C6E0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4200 000021A6 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4201 000021A8 803D[2C6E0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4202 000021AF 743C                <1> 	JZ	short NO_RETRY
  4203 000021B1 8AA7[396E0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4204 000021B7 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4205 000021BA 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4206 000021BC 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4207 000021BF 8A2D[346E0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4208 000021C5 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4209 000021C8 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4210 000021CB 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4211 000021CD 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4212                              <1> 
  4213                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4214                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4215                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4216                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4217                              <1> 
  4218 000021CF 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4219 000021D2 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4220 000021D4 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4221 000021D7 80A7[396E0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4222                              <1> 					; RATE, DBL STEP OFF
  4223 000021DE 08A7[396E0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4224 000021E4 C605[2C6E0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4225 000021EB F9                  <1> 	STC				; SET CARRY FOR RETRY
  4226 000021EC C3                  <1> 	RETn				; RETRY RETURN
  4227                              <1> 
  4228                              <1> NO_RETRY:
  4229 000021ED F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4230 000021EE C3                  <1> 	RETn				; NO RETRY RETURN
  4231                              <1> 
  4232                              <1> ;-------------------------------------------------------------------------------
  4233                              <1> ; NUM_TRANS
  4234                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4235                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4236                              <1> ;
  4237                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4238                              <1> ;		SI-HI  = HEAD
  4239                              <1> ;		[BP]   = START SECTOR
  4240                              <1> ;
  4241                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4242                              <1> ;-------------------------------------------------------------------------------
  4243                              <1> NUM_TRANS:
  4244 000021EF 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4245 000021F1 803D[2C6E0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4246                              <1> 	; 05/12/2021
  4247 000021F8 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4248 000021FA B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4249 000021FC E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4250 00002201 8A1D[326E0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4251 00002207 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4252 0000220A 3A2D[316E0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4253 00002210 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4254 00002212 8A2D[306E0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4255 00002218 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4256 0000221B 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4257 0000221D 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4258                              <1> DIF_HD:
  4259 0000221F 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4260                              <1> SAME_TRK:
  4261 00002221 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4262 00002224 88D8                <1> 	MOV	AL,BL			; TO AL
  4263                              <1> NT_OUT:
  4264 00002226 C3                  <1> 	RETn
  4265                              <1> 
  4266                              <1> ;-------------------------------------------------------------------------------
  4267                              <1> ; SETUP_END
  4268                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4269                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4270                              <1> ;
  4271                              <1> ; ON EXIT:
  4272                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4273                              <1> ;-------------------------------------------------------------------------------
  4274                              <1> SETUP_END:
  4275 00002227 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4276                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4277 00002229 50                  <1> 	push	eax ; 05/12/2021
  4278 0000222A E8C6000000          <1> 	CALL	GET_PARM
  4279 0000222F 8825[2B6E0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4280                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4281 00002235 58                  <1> 	pop	eax ; 05/12/2021
  4282 00002236 8A25[2C6E0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4283 0000223C 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4284 0000223E 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4285 00002240 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4286                              <1> NUN_ERR: 
  4287 00002242 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4288 00002245 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4289 00002246 C3                  <1> 	RETn
  4290                              <1> 
  4291                              <1> ;-------------------------------------------------------------------------------
  4292                              <1> ; SETUP_DBL
  4293                              <1> ;	CHECK DOUBLE STEP.
  4294                              <1> ;
  4295                              <1> ; ON ENTRY :	DI = DRIVE
  4296                              <1> ;
  4297                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4298                              <1> ;-------------------------------------------------------------------------------
  4299                              <1> SETUP_DBL:
  4300 00002247 8AA7[396E0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4301 0000224D F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4302 00002250 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4303                              <1> 
  4304                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4305                              <1> 
  4306 00002252 C605[296E0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4307 00002259 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4308 0000225E B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4309 00002260 E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4310 00002265 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4311 0000226A 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4312                              <1> 
  4313                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4314                              <1> 
  4315 0000226C 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4316 00002270 F687[396E0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4317 00002277 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4318 00002279 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4319                              <1> 
  4320                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4321                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4322                              <1> ;	THEN SET DOUBLE STEP ON.
  4323                              <1> 
  4324                              <1> CNT_OK:
  4325 0000227B C605[2B6E0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4326                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4327                              <1> 	; 05/12/2021
  4328 00002282 51                  <1> 	push	ecx
  4329 00002283 C605[2C6E0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4330 0000228A 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4331 0000228D D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4332 0000228F C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4333                              <1> 	;PUSH	AX			; SAVE HEAD
  4334                              <1> 	; 05/12/2021
  4335 00002292 50                  <1> 	push	eax
  4336 00002293 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4337                              <1> 	;POP	AX			; RESTORE HEAD
  4338                              <1> 	; 05/12/2021
  4339 00002298 58                  <1> 	pop	eax
  4340 00002299 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4341 0000229C E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4342 000022A1 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4343 000022A2 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4344 000022A7 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4345                              <1> 	;POP	CX			; RESTORE COUNT
  4346                              <1> 	; 05/12/2021
  4347 000022A8 59                  <1> 	pop	ecx
  4348 000022A9 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4349 000022AB FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4350 000022AD 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4351 000022AF 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4352                              <1> 
  4353                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4354                              <1> 
  4355                              <1> SD_ERR:	
  4356 000022B1 F9                  <1> 	STC				; SET CARRY FOR ERROR
  4357 000022B2 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4358                              <1> 
  4359                              <1> DO_CHK:
  4360 000022B3 8A0D[306E0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4361 000022B9 888F[3D6E0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4362 000022BF D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4363 000022C1 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4364 000022C3 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4365 000022C5 808F[396E0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4366                              <1> NO_DBL:
  4367 000022CC F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4368 000022CD C3                  <1> 	RETn
  4369                              <1> 
  4370                              <1> ;-------------------------------------------------------------------------------
  4371                              <1> ; READ_ID
  4372                              <1> ;	READ ID FUNCTION.
  4373                              <1> ;
  4374                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4375                              <1> ;
  4376                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4377                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4378                              <1> ;-------------------------------------------------------------------------------
  4379                              <1> READ_ID:
  4380 000022CE B8[EB220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4381 000022D3 50                  <1> 	PUSH	eAX
  4382 000022D4 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4383 000022D6 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4384 000022DB 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4385 000022DE 88C4                <1> 	MOV	AH,AL
  4386 000022E0 E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4387 000022E5 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4388 000022EA 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4389                              <1> ER_3:
  4390 000022EB C3                  <1> 	RETn
  4391                              <1> 
  4392                              <1> ;-------------------------------------------------------------------------------
  4393                              <1> ; CMOS_TYPE
  4394                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4395                              <1> ;
  4396                              <1> ; ON ENTRY:	DI = DRIVE #
  4397                              <1> ;
  4398                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4399                              <1> ;-------------------------------------------------------------------------------
  4400                              <1> 
  4401                              <1> CMOS_TYPE: ; 11/12/2014
  4402 000022EC 8A87[9E680000]      <1> 	mov	al, [eDI+fd0_type]
  4403 000022F2 20C0                <1> 	and 	al, al ; 18/12/2014
  4404 000022F4 C3                  <1> 	retn
  4405                              <1> 
  4406                              <1> ;CMOS_TYPE:
  4407                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4408                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4409                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4410                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4411                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4412                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4413                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4414                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4415                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4416                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4417                              <1> ;TB:
  4418                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4419                              <1> ;BAD_CM:
  4420                              <1> ;	RETn				; CY, STATUS OF READ
  4421                              <1> 
  4422                              <1> ;-------------------------------------------------------------------------------
  4423                              <1> ; GET_PARM
  4424                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4425                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4426                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4427                              <1> ;	THE PARAMETER IN DL.
  4428                              <1> ;
  4429                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4430                              <1> ;
  4431                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4432                              <1> ;		AL,DH DESTROYED
  4433                              <1> ;-------------------------------------------------------------------------------
  4434                              <1> GET_PARM:
  4435                              <1> 	;PUSH	DS
  4436 000022F5 56                  <1> 	PUSH	eSI
  4437                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4438                              <1>     	;MOV	DS,AX
  4439                              <1> 	;;mov	ax, cs
  4440                              <1> 	;;mov	ds, ax
  4441                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4442 000022F6 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4443                              <1> 	;SUB	BH,BH			; BX = INDEX
  4444 000022F8 81E3FF000000        <1> 	and	ebx, 0FFh
  4445                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4446                              <1> 	;
  4447                              <1> 	; 17/12/2014
  4448 000022FE 66A1[91680000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4449 00002304 38E0                <1> 	cmp	al, ah
  4450 00002306 7425                <1> 	je	short gpndc
  4451 00002308 A2[92680000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4452 0000230D 53                  <1> 	push	ebx ; 08/02/2015
  4453 0000230E 88C3                <1> 	mov	bl, al 
  4454                              <1> 	; 11/12/2014
  4455 00002310 8A83[9E680000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4456                              <1> 	; 18/12/2014
  4457 00002316 20C0                <1> 	and	al, al
  4458 00002318 7507                <1> 	jnz	short gpdtc
  4459 0000231A BB[7B680000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4460 0000231F EB05                <1>         jmp     short gpdpu
  4461                              <1> gpdtc:	
  4462 00002321 E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4463                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4464                              <1> gpdpu:
  4465 00002326 891D[18680000]      <1> 	mov	[DISK_POINTER], ebx
  4466 0000232C 5B                  <1> 	pop	ebx
  4467                              <1> gpndc:
  4468 0000232D 8B35[18680000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4469 00002333 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4470 00002336 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4471 00002338 5E                  <1> 	POP	eSI
  4472                              <1> 	;POP	DS
  4473 00002339 C3                  <1> 	RETn
  4474                              <1> 
  4475                              <1> ;-------------------------------------------------------------------------------
  4476                              <1> ; MOTOR_ON
  4477                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4478                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4479                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4480                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4481                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4482                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4483                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4484                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4485                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4486                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4487                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4488                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4489                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4490                              <1> ;
  4491                              <1> ; ON ENTRY:	DI = DRIVE #
  4492                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4493                              <1> ;-------------------------------------------------------------------------------
  4494                              <1> MOTOR_ON:
  4495 0000233A 53                  <1> 	PUSH	eBX			; SAVE REG.
  4496 0000233B E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4497 00002340 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4498 00002342 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4499 00002347 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4500                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4501                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4502                              <1> M_WAIT:
  4503 0000234C B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4504 0000234E E8A2FFFFFF          <1> 	CALL	GET_PARM
  4505                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4506                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4507                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4508 00002353 80FC08              <1> 	cmp	ah, 8
  4509                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4510 00002356 7702                <1> 	ja	short J13
  4511                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4512 00002358 B408                <1> 	mov	ah, 8
  4513                              <1> 
  4514                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4515                              <1> GP2:	
  4516                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4517                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4518 0000235A B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4519 0000235F E867F1FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4520                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4521 00002364 FECC                <1> 	dec	ah
  4522 00002366 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4523                              <1> MOT_IS_ON:
  4524 00002368 5B                  <1> 	POP	eBX			; RESTORE REG.
  4525 00002369 C3                  <1> 	RETn
  4526                              <1> 
  4527                              <1> ;-------------------------------------------------------------------------------
  4528                              <1> ; TURN_ON
  4529                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4530                              <1> ;
  4531                              <1> ; ON ENTRY:	DI = DRIVE #
  4532                              <1> ;
  4533                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4534                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4535                              <1> ;		AX,BX,CX,DX DESTROYED
  4536                              <1> ;-------------------------------------------------------------------------------
  4537                              <1> TURN_ON:
  4538 0000236A 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4539 0000236C 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4540 0000236E C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4541 00002371 FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4542 00002372 C605[2B6E0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4543 00002379 A0[2A6E0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4544 0000237E 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4545 00002380 B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4546 00002382 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4547                              <1> 
  4548                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4549                              <1> ;  BL = DRIVE SELECT DESIRED
  4550                              <1> ;  AH = MOTOR ON MASK DESIRED
  4551                              <1> 
  4552 00002384 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4553 00002386 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4554 00002388 8425[2A6E0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4555 0000238E 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4556                              <1> 
  4557                              <1> TURN_IT_ON:
  4558 00002390 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4559 00002392 8A3D[2A6E0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4560 00002398 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4561 0000239B 8025[2A6E0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4562 000023A2 0825[2A6E0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4563 000023A8 A0[2A6E0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4564 000023AD 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4565 000023AF 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4566 000023B2 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4567 000023B3 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4568 000023B5 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4569 000023B8 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4570 000023BA 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4571 000023BE EE                  <1> 	OUT	DX,AL
  4572 000023BF 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4573                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4574 000023C1 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4575 000023C3 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4576 000023C4 C3                  <1> 	RETn
  4577                              <1> 
  4578                              <1> NO_MOT_WAIT:
  4579 000023C5 FB                  <1> 	sti
  4580                              <1> no_mot_w1: ; 27/02/2015
  4581 000023C6 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4582                              <1> 	;STI				; INTERRUPTS BACK ON
  4583 000023C7 C3                  <1> 	RETn
  4584                              <1> 
  4585                              <1> ;-------------------------------------------------------------------------------
  4586                              <1> ; HD_WAIT
  4587                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4588                              <1> ;
  4589                              <1> ; ON ENTRY:	DI = DRIVE #
  4590                              <1> ;
  4591                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4592                              <1> ;-------------------------------------------------------------------------------
  4593                              <1> HD_WAIT:
  4594 000023C8 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4595 000023CA E826FFFFFF          <1> 	CALL	GET_PARM
  4596 000023CF 08E4                <1> 	or	ah, ah	; 17/12/2014
  4597 000023D1 7519                <1> 	jnz	short DO_WAT
  4598 000023D3 F605[2A6E0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4599                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4600                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4601                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4602 000023DA 741E                <1> 	jz	short HW_DONE
  4603 000023DC B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4604 000023DE 8A87[396E0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4605 000023E4 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4606 000023E6 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4607 000023E8 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4608                              <1> ;GP3:
  4609 000023EA B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4610                              <1> ;	JMP	SHORT DO_WAT
  4611                              <1> 
  4612                              <1> ;ISNT_WRITE:
  4613                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4614                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4615                              <1> 
  4616                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4617                              <1> DO_WAT:
  4618                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4619                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4620                              <1> J29:					; 	1 MILLISECOND LOOP
  4621                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4622 000023EC B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4623 000023F1 E8D5F0FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4624                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4625 000023F6 FECC                <1> 	dec	ah
  4626 000023F8 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4627                              <1> HW_DONE:
  4628 000023FA C3                  <1> 	RETn
  4629                              <1> 
  4630                              <1> ;-------------------------------------------------------------------------------
  4631                              <1> ; NEC_OUTPUT
  4632                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4633                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4634                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4635                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4636                              <1> ; 
  4637                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4638                              <1> ;
  4639                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4640                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4641                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4642                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4643                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4644                              <1> ;		AX,CX,DX DESTROYED
  4645                              <1> ;-------------------------------------------------------------------------------
  4646                              <1> 
  4647                              <1> ; 09/12/2014 [Erdogan Tan] 
  4648                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4649                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4650                              <1> ;	This read only register facilitates the transfer of data between
  4651                              <1> ;	the system microprocessor and the controller.
  4652                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4653                              <1> ;	  with the system micrprocessor.
  4654                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4655                              <1> ;	  the transfer is to the controller.
  4656                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4657                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4658                              <1> ; Bit 3 - Reserved.
  4659                              <1> ; Bit 2 - Reserved.
  4660                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4661                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4662                              <1> 
  4663                              <1> ; Data Register (3F5h)
  4664                              <1> ; This read/write register passes data, commands and parameters, and provides
  4665                              <1> ; diskette status information.
  4666                              <1>   		
  4667                              <1> NEC_OUTPUT:
  4668                              <1> 	;PUSH	BX			; SAVE REG.
  4669 000023FB 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4670                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4671                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4672                              <1> 	; 16/12/2014
  4673                              <1> 	; waiting for (max.) 0.5 seconds
  4674                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4675                              <1> 	;
  4676                              <1> 	; 17/12/2014
  4677                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4678                              <1> 	;
  4679                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4680                              <1> 	;		go on.
  4681                              <1> 	;INPUT:
  4682                              <1> 	;	AH=Mask for isolation bits.
  4683                              <1> 	;	AL=pattern to look for.
  4684                              <1> 	;	DX=Port to test for
  4685                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4686                              <1> 	;	     (normally 30 microseconds per period.)
  4687                              <1> 	;
  4688                              <1> 	;WFP_SHORT:  
  4689                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4690                              <1> 	;
  4691                              <1> 
  4692                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4693                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4694 000023FF B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4695                              <1> ;
  4696                              <1> ;WFPS_OUTER_LP:
  4697                              <1> ;	;
  4698                              <1> ;WFPS_CHECK_PORT:
  4699                              <1> J23:
  4700 00002404 EC                  <1> 	IN	AL,DX			; GET STATUS
  4701 00002405 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4702 00002407 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4703 00002409 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4704                              <1> WFPS_HI:
  4705 0000240B E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4706 0000240D A810                <1> 	TEST	AL,010H			; transition on memory
  4707 0000240F 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4708                              <1> WFPS_LO:
  4709 00002411 E461                <1> 	IN	AL, PORT_B		; SYS1
  4710 00002413 A810                <1> 	TEST	AL,010H
  4711 00002415 74FA                <1> 	JZ	SHORT WFPS_LO
  4712                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4713 00002417 E2EB                <1> 	loop	J23	; 27/02/2015
  4714                              <1> ;	;
  4715                              <1> ;	dec	bl
  4716                              <1> ;	jnz	short WFPS_OUTER_LP
  4717                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4718                              <1> ;J23:
  4719                              <1> ;	IN	AL,DX			; GET STATUS
  4720                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4721                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4722                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4723                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4724                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4725                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4726                              <1>    
  4727                              <1> 	;;27/02/2015
  4728                              <1> 	;16/12/2014
  4729                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4730                              <1> 	;;jb	short J23
  4731                              <1> 
  4732                              <1> ;WFPS_TIMEOUT:
  4733                              <1> 
  4734                              <1> ;-----	FALL THRU TO ERROR RETURN
  4735                              <1> 
  4736 00002419 800D[2C6E0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4737                              <1> 	;POP	BX			; RESTORE REG.
  4738 00002420 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4739 00002421 F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4740 00002422 C3                  <1> 	RETn
  4741                              <1> 
  4742                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4743                              <1> 
  4744                              <1> J27:	
  4745 00002423 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4746 00002425 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4747 00002427 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4748                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4749                              <1> 	; 27/02/2015
  4750 00002428 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE FLAGS
  4751                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4752 00002429 29C9                <1> 	sub	ecx, ecx
  4753 0000242B B103                <1> 	mov	cl, 3 ; 05/12/2021
  4754 0000242D E899F0FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4755 00002432 9D                  <1> 	POPFd	; 05/12/2021			; RESTORE FLAGS FOR EXIT
  4756                              <1> 	;POP	BX			; RESTORE REG
  4757 00002433 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4758                              <1> 
  4759                              <1> ;-------------------------------------------------------------------------------
  4760                              <1> ; SEEK
  4761                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4762                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4763                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4764                              <1> ;
  4765                              <1> ; ON ENTRY:	DI = DRIVE #
  4766                              <1> ;		CH = TRACK #
  4767                              <1> ;
  4768                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4769                              <1> ;		AX,BX,CX DX DESTROYED
  4770                              <1> ;-------------------------------------------------------------------------------
  4771                              <1> SEEK:
  4772 00002434 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4773 00002436 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4774 00002438 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4775 0000243A D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4776 0000243C 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4777 0000243E 8405[296E0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4778 00002444 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4779                              <1> 
  4780 00002446 0805[296E0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4781 0000244C E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4782 00002451 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4783                              <1> 
  4784                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4785                              <1> 
  4786 00002453 C605[2C6E0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4787 0000245A E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4788 0000245F 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4789                              <1> 
  4790                              <1> AFT_RECAL:
  4791 00002461 C687[3D6E0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4792 00002468 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4793 0000246A 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4794                              <1> 
  4795                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4796                              <1> 
  4797 0000246C F687[396E0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4798 00002473 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4799 00002475 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4800                              <1> 
  4801 00002477 3AAF[3D6E0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4802 0000247D 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4803                              <1> 
  4804 0000247F BA[B2240000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4805 00002484 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4806 00002485 88AF[3D6E0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4807 0000248B B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4808 0000248D E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4809 00002492 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4810 00002494 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4811 00002496 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4812 0000249B 8AA7[3D6E0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4813 000024A1 E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4814 000024A6 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4815                              <1> 
  4816                              <1> ;-----	WAIT FOR HEAD SETTLE
  4817                              <1> 
  4818                              <1> DO_WAIT:
  4819 000024AB 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE STATUS
  4820 000024AC E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4821 000024B1 9D                  <1> 	POPFd	; 05/12/2021		; RESTORE STATUS
  4822                              <1> RB:
  4823                              <1> NEC_ERR:
  4824                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4825                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4826 000024B2 C3                  <1> 	RETn				; RETURN TO CALLER
  4827                              <1> 
  4828                              <1> ;-------------------------------------------------------------------------------
  4829                              <1> ; RECAL
  4830                              <1> ;	RECALIBRATE DRIVE
  4831                              <1> ;
  4832                              <1> ; ON ENTRY:	DI = DRIVE #
  4833                              <1> ;
  4834                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4835                              <1> ;-------------------------------------------------------------------------------
  4836                              <1> RECAL:
  4837                              <1> 	;PUSH	CX
  4838                              <1> 	; 05/12/2021
  4839 000024B3 51                  <1> 	push	ecx
  4840 000024B4 B8[D0240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4841 000024B9 50                  <1> 	PUSH	eAX
  4842 000024BA B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4843 000024BC E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4844 000024C1 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4845 000024C3 88DC                <1> 	MOV	AH,BL
  4846 000024C5 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4847 000024CA E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4848 000024CF 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4849                              <1> RC_BACK:
  4850                              <1> 	;POP	CX
  4851                              <1> 	; 05/12/2021
  4852 000024D0 59                  <1> 	pop	ecx
  4853 000024D1 C3                  <1> 	RETn
  4854                              <1> 
  4855                              <1> ;-------------------------------------------------------------------------------
  4856                              <1> ; CHK_STAT_2
  4857                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4858                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4859                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4860                              <1> ;
  4861                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4862                              <1> ;-------------------------------------------------------------------------------
  4863                              <1> CHK_STAT_2:
  4864 000024D2 B8[FA240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4865 000024D7 50                  <1> 	PUSH	eAX
  4866 000024D8 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4867 000024DD 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4868 000024DF B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4869 000024E1 E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4870 000024E6 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4871 000024EB 720C                <1> 	JC	short J34
  4872 000024ED A0[2D6E0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4873 000024F2 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4874 000024F4 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4875 000024F6 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4876 000024F8 F8                  <1> 	CLC				; GOOD RETURN
  4877                              <1> J34:
  4878 000024F9 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4879                              <1> CS_BACK:
  4880 000024FA C3                  <1> 	RETn
  4881                              <1> J35:
  4882 000024FB 800D[2C6E0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4883 00002502 F9                  <1> 	STC				; ERROR RETURN CODE
  4884 00002503 EBF4                <1> 	JMP	SHORT J34
  4885                              <1> 
  4886                              <1> ;-------------------------------------------------------------------------------
  4887                              <1> ; WAIT_INT
  4888                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4889                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4890                              <1> ;	IF THE DRIVE IS NOT READY.
  4891                              <1> ;
  4892                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4893                              <1> ;-------------------------------------------------------------------------------
  4894                              <1> 
  4895                              <1> ; 17/12/2014
  4896                              <1> ; 2.5 seconds waiting !
  4897                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4898                              <1> ; amount of time to wait for completion interrupt from NEC.
  4899                              <1> 
  4900                              <1> 
  4901                              <1> WAIT_INT:
  4902 00002505 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4903 00002506 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4904                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4905                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4906                              <1> 
  4907                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4908                              <1> 	;
  4909                              <1> 	;WAIT_FOR_MEM:	
  4910                              <1> 	;	Waits for a bit at a specified memory location pointed
  4911                              <1> 	;	to by ES:[DI] to become set.
  4912                              <1> 	;INPUT:
  4913                              <1> 	;	AH=Mask to test with.
  4914                              <1> 	;	ES:[DI] = memory location to watch.
  4915                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4916                              <1> 	;	     (normally 30 microseconds per period.)
  4917                              <1> 
  4918                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4919                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4920                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4921                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4922                              <1> 	; 27/02/2015
  4923 00002507 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4924                              <1> WFMS_CHECK_MEM:
  4925 0000250C F605[296E0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4926 00002513 7516                <1>         jnz     short J37
  4927                              <1> WFMS_HI:
  4928 00002515 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4929 00002517 A810                <1> 	TEST	AL,010H			; transition on memory
  4930 00002519 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4931                              <1> WFMS_LO:
  4932 0000251B E461                <1> 	IN	AL,PORT_B		;SYS1
  4933 0000251D A810                <1> 	TEST	AL,010H
  4934 0000251F 74FA                <1> 	JZ	SHORT WFMS_LO
  4935 00002521 E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4936                              <1> ;WFMS_OUTER_LP:
  4937                              <1> ;;	or	bl, bl			; check outer counter
  4938                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4939                              <1> ;	dec	bl
  4940                              <1> ;	jz	short J36A	
  4941                              <1> ;	jmp	short WFMS_CHECK_MEM
  4942                              <1> 
  4943                              <1> 	;17/12/2014
  4944                              <1> 	;16/12/2014
  4945                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4946                              <1> ;J36:
  4947                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4948                              <1> ;	JNZ	short J37
  4949                              <1> 	;16/12/2014
  4950                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4951                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4952                              <1> 	;JNZ	short J36
  4953                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4954                              <1> ;	jb	short J36
  4955                              <1> 
  4956                              <1> ;WFMS_TIMEOUT:
  4957                              <1> ;J36A:
  4958 00002523 800D[2C6E0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4959 0000252A F9                  <1> 	STC				; ERROR RETURN
  4960                              <1> J37:
  4961 0000252B 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4962 0000252C 8025[296E0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4963 00002533 9D                  <1> 	POPF				; RECOVER CARRY
  4964 00002534 C3                  <1> 	RETn				; GOOD RETURN CODE
  4965                              <1> 
  4966                              <1> ;-------------------------------------------------------------------------------
  4967                              <1> ; RESULTS
  4968                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4969                              <1> ;	FOLLOWING AN INTERRUPT.
  4970                              <1> ;
  4971                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4972                              <1> ;		AX,BX,CX,DX DESTROYED
  4973                              <1> ;-------------------------------------------------------------------------------
  4974                              <1> RESULTS:
  4975 00002535 57                  <1> 	PUSH	eDI
  4976 00002536 BF[2D6E0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4977 0000253B B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4978 0000253D 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4979                              <1> 
  4980                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4981                              <1> 
  4982                              <1> _R10: 
  4983                              <1> 	; 16/12/2014
  4984                              <1> 	; wait for (max) 0.5 seconds
  4985                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4986                              <1> 	;XOR	CX,CX			; COUNTER
  4987                              <1> 
  4988                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4989                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4990                              <1> 	; 27/02/2015
  4991 00002541 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4992                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4993                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4994                              <1> 
  4995                              <1> WFPSR_OUTER_LP:
  4996                              <1> 	;
  4997                              <1> WFPSR_CHECK_PORT:
  4998                              <1> J39:					; WAIT FOR MASTER
  4999 00002546 EC                  <1> 	IN	AL,DX			; GET STATUS
  5000 00002547 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5001 00002549 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5002 0000254B 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  5003                              <1> WFPSR_HI:
  5004 0000254D E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  5005 0000254F A810                <1> 	TEST	AL,010H			; transition on memory
  5006 00002551 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  5007                              <1> WFPSR_LO:
  5008 00002553 E461                <1> 	IN	AL, PORT_B		; SYS1
  5009 00002555 A810                <1> 	TEST	AL,010H
  5010 00002557 74FA                <1> 	JZ	SHORT WFPSR_LO
  5011 00002559 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  5012                              <1> 	;; 27/02/2015
  5013                              <1> 	;;dec	bh
  5014                              <1> 	;;jnz	short WFPSR_OUTER_LP
  5015                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  5016                              <1> 
  5017                              <1> 	;;mov	byte [wait_count], 0
  5018                              <1> ;J39:					; WAIT FOR MASTER
  5019                              <1> ;	IN	AL,DX			; GET STATUS
  5020                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5021                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5022                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  5023                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  5024                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  5025                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  5026                              <1> 	;
  5027                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  5028                              <1> 	;;jb	short J39	
  5029                              <1> 
  5030                              <1> ;WFPSR_TIMEOUT:
  5031 0000255B 800D[2C6E0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5032 00002562 F9                  <1> 	STC				; SET ERROR RETURN
  5033 00002563 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5034                              <1> 
  5035                              <1> ;-----	READ IN THE STATUS
  5036                              <1> 
  5037                              <1> J42:
  5038 00002565 EB00                <1> 	JMP	$+2			; I/O DELAY
  5039 00002567 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5040 00002569 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5041                              <1> 	; 16/12/2014
  5042                              <1> 	NEWIODELAY
  2138 0000256A E6EB                <2>  out 0EBh,al
  5043 0000256C 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5044 0000256E 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5045                              <1> 	; 16/12/2014
  5046                              <1> ;	push	cx
  5047                              <1> ;	mov	cx, 30
  5048                              <1> ;wdw2:
  5049                              <1> ;	NEWIODELAY
  5050                              <1> ;	loop	wdw2
  5051                              <1> ;	pop	cx
  5052                              <1> 
  5053 0000256F B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5054 00002574 E852EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5055 00002579 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5056 0000257B EC                  <1> 	IN	AL,DX			; GET STATUS
  5057                              <1> 	; 16/12/2014
  5058                              <1> 	NEWIODELAY
  2138 0000257C E6EB                <2>  out 0EBh,al
  5059                              <1> 	;
  5060 0000257E A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5061 00002580 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5062                              <1> 
  5063 00002582 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5064 00002584 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5065 00002586 800D[2C6E0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5066 0000258D F9                  <1> 	STC				; SET ERROR FLAG
  5067                              <1> 
  5068                              <1> ;-----	RESULT OPERATION IS DONE
  5069                              <1> POPRES:
  5070 0000258E 5F                  <1> 	POP	eDI
  5071 0000258F C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5072                              <1> 
  5073                              <1> ;-------------------------------------------------------------------------------
  5074                              <1> ; READ_DSKCHNG
  5075                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5076                              <1> ;
  5077                              <1> ; ON ENTRY:	DI = DRIVE #
  5078                              <1> ;
  5079                              <1> ; ON EXIT:	DI = DRIVE #
  5080                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5081                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5082                              <1> ;		AX,CX,DX DESTROYED
  5083                              <1> ;-------------------------------------------------------------------------------
  5084                              <1> READ_DSKCHNG:
  5085 00002590 E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5086 00002595 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5087 00002599 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5088 0000259A A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5089 0000259C C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5090                              <1> 
  5091                              <1> ;-------------------------------------------------------------------------------
  5092                              <1> ; DRIVE_DET
  5093                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5094                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5095                              <1> ; ON ENTRY:	DI = DRIVE #
  5096                              <1> ;-------------------------------------------------------------------------------
  5097                              <1> DRIVE_DET:
  5098 0000259D E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5099 000025A2 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5100 000025A7 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5101 000025A9 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5102 000025AB E884FEFFFF          <1> 	CALL	SEEK
  5103 000025B0 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5104 000025B2 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5105                              <1> SK_GIN:
  5106 000025B4 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5107                              <1> 	;PUSH	CX			; SAVE TRACK
  5108                              <1> 	; 05/12/2021
  5109 000025B6 51                  <1> 	push	ecx
  5110 000025B7 E878FEFFFF          <1> 	CALL	SEEK
  5111 000025BC 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5112 000025BE B8[F9250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5113 000025C3 50                  <1> 	PUSH	eAX
  5114 000025C4 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5115 000025C6 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5116 000025CB 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5117 000025CE 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5118 000025D0 E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5119 000025D5 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5120 000025DA 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5121                              <1> 	;POP	CX			; RESTORE TRACK
  5122                              <1> 	; 05/12/2021
  5123 000025DB 59                  <1> 	pop	ecx
  5124 000025DC F605[2D6E0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5125 000025E3 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5126 000025E5 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5127 000025E7 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5128                              <1> 
  5129                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5130                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5131                              <1> 
  5132 000025E9 808F[396E0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5133 000025F0 C3                  <1> 	RETn				; ALL INFORMATION SET
  5134                              <1> IS_80:
  5135 000025F1 808F[396E0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5136                              <1> DD_BAC:
  5137 000025F8 C3                  <1> 	RETn
  5138                              <1> POP_BAC:
  5139                              <1> 	;POP	CX			; THROW AWAY
  5140                              <1> 	; 05/12/2021
  5141 000025F9 59                  <1> 	pop	ecx
  5142 000025FA C3                  <1> 	RETn
  5143                              <1> 
  5144                              <1> fdc_int:  
  5145                              <1> 	  ; 30/07/2015	
  5146                              <1> 	  ; 16/02/2015
  5147                              <1> ;int_0Eh: ; 11/12/2014
  5148                              <1> 
  5149                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5150                              <1> ; DISK_INT
  5151                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5152                              <1> ;
  5153                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5154                              <1> ;-------------------------------------------------------------------------------
  5155                              <1> DISK_INT_1:
  5156                              <1> 
  5157                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5158                              <1> 	; 05/12/2021
  5159 000025FB 50                  <1> 	push	eax
  5160 000025FC 1E                  <1> 	push	ds
  5161 000025FD 66B81000            <1> 	mov	ax, KDATA
  5162 00002601 8ED8                <1> 	mov 	ds, ax
  5163 00002603 800D[296E0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5164 0000260A B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5165 0000260C E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5166 0000260E 1F                  <1> 	pop	ds
  5167                              <1> 	;POP	AX			; RECOVER REGISTER
  5168                              <1> 	; 05/12/2021
  5169 0000260F 58                  <1> 	pop	eax
  5170 00002610 CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5171                              <1> 
  5172                              <1> ;-------------------------------------------------------------------------------
  5173                              <1> ; DSKETTE_SETUP
  5174                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5175                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5176                              <1> ;-------------------------------------------------------------------------------
  5177                              <1> DSKETTE_SETUP:
  5178                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5179                              <1> 	;PUSH	BX
  5180                              <1> 	;PUSH	CX
  5181 00002611 52                  <1> 	PUSH	eDX
  5182                              <1> 	;PUSH	DI
  5183                              <1> 	;;PUSH	DS
  5184                              <1> 	; 14/12/2014
  5185                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5186                              <1> 	;mov	[DISK_POINTER+2], cs
  5187                              <1> 	;
  5188                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5189 00002612 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5190 00002614 66C705[396E0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5190 0000261C 00                  <1>
  5191 0000261D 8025[346E0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5192 00002624 800D[346E0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5193 0000262B C605[296E0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5194 00002632 C605[2B6E0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5195 00002639 C605[2A6E0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5196 00002640 C605[2C6E0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5197                              <1> 	;
  5198                              <1> 	; 28/02/2015
  5199                              <1> 	;mov	word [cfd], 100h 
  5200 00002647 E89DF2FFFF          <1> 	call	DSK_RESET
  5201 0000264C 5A                  <1> 	pop	edx
  5202 0000264D C3                  <1> 	retn
  5203                              <1> 
  5204                              <1> ;SUP0:
  5205                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5206                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5207                              <1> ;	; 02/01/2015
  5208                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5209                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5210                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5211                              <1> ;       cmp     byte [fd1_type], 0	
  5212                              <1> ;	jna	short sup1
  5213                              <1> ;	or	di, di
  5214                              <1> ;	jnz	short sup1
  5215                              <1> ;	inc	di
  5216                              <1> ;       jmp     short SUP0
  5217                              <1> ;sup1:
  5218                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5219                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5220                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5221                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5222                              <1> ;	;POP	DI
  5223                              <1> ;	POP	eDX
  5224                              <1> ;	;POP	CX
  5225                              <1> ;	;POP	BX
  5226                              <1> ;	;POP	AX
  5227                              <1> ;	RETn
  5228                              <1> 
  5229                              <1> ;//////////////////////////////////////////////////////
  5230                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5231                              <1> ;
  5232                              <1> 
  5233                              <1> int13h: ; 21/02/2015
  5234 0000264E 9C                  <1> 	pushfd
  5235 0000264F 0E                  <1> 	push 	cs
  5236 00002650 E858000000          <1> 	call 	DISK_IO
  5237 00002655 C3                  <1> 	retn
  5238                              <1> 
  5239                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5240                              <1> ;/////////////////////////////////////////////////////////////////////
  5241                              <1> 
  5242                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5243                              <1> ; 23/02/2015
  5244                              <1> ; 21/02/2015 (unix386.s)
  5245                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5246                              <1> ;
  5247                              <1> ; Original Source Code:
  5248                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5249                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5250                              <1> ;
  5251                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5252                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5253                              <1> ;
  5254                              <1> 
  5255                              <1> ;The wait for controller to be not busy is 10 seconds.
  5256                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5257                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5258                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5259                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5260                              <1> 
  5261                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5262                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5263                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5264                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5265                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5266                              <1> 
  5267                              <1> ;The wait for Data request on read and write longs is
  5268                              <1> ;2000 us. (?)
  5269                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5270                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5271                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5272                              <1> 
  5273                              <1> ; Port 61h (PORT_B)
  5274                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5275                              <1> 
  5276                              <1> ; 23/12/2014
  5277                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5278                              <1> 
  5279                              <1> ;--- INT 13H -------------------------------------------------------------------
  5280                              <1> ;									       :
  5281                              <1> ; FIXED DISK I/O INTERFACE						       :
  5282                              <1> ;									       :
  5283                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5284                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5285                              <1> ;									       :
  5286                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5287                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5288                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5289                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5290                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5291                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5292                              <1> ;									       :
  5293                              <1> ;------------------------------------------------------------------------------:
  5294                              <1> ;									       :
  5295                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5296                              <1> ;									       :
  5297                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5298                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5299                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5300                              <1> ;			  DL > 80H - DISK				       :
  5301                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5302                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5303                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5304                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5305                              <1> ;	(AH)= 06H  UNUSED						       :
  5306                              <1> ;	(AH)= 07H  UNUSED						       :
  5307                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5308                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5309                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5310                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5311                              <1> ;	(AH)= 0AH  READ LONG						       :
  5312                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5313                              <1> ;	(AH)= 0CH  SEEK 						       :
  5314                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5315                              <1> ;	(AH)= 0EH  UNUSED						       :
  5316                              <1> ;	(AH)= 0FH  UNUSED						       :
  5317                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5318                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5319                              <1> ;	(AH)= 12H  UNUSED						       :
  5320                              <1> ;	(AH)= 13H  UNUSED						       :
  5321                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5322                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5323                              <1> ;									       :
  5324                              <1> ;-------------------------------------------------------------------------------
  5325                              <1> ;									       :
  5326                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5327                              <1> ;									       :
  5328                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5329                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5330                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5331                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5332                              <1> ;									       :
  5333                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5334                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5335                              <1> ;				 (10 BITS TOTAL)			       :
  5336                              <1> ;									       :
  5337                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5338                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5339                              <1> ;									       :
  5340                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5341                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5342                              <1> ;									       :
  5343                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5344                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5345                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5346                              <1> ;			       80H FOR A BAD SECTOR			       :
  5347                              <1> ;			   N = SECTOR NUMBER				       :
  5348                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5349                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5350                              <1> ;									       :
  5351                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5352                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5353                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5354                              <1> ;									       :
  5355                              <1> ;-------------------------------------------------------------------------------
  5356                              <1> 
  5357                              <1> ;-------------------------------------------------------------------------------
  5358                              <1> ; OUTPUT								       :
  5359                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5360                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5361                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5362                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5363                              <1> ;									       :
  5364                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5365                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5366                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5367                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5368                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5369                              <1> ;		REWRITTEN.						       :
  5370                              <1> ;									       :
  5371                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5372                              <1> ;	   INPUT:							       :
  5373                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5374                              <1> ;	   OUTPUT:							       :
  5375                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5376                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5377                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5378                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5379                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5380                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5381                              <1> ;									       :
  5382                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5383                              <1> ;									       :
  5384                              <1> ;	AH = 0 - NOT PRESENT						       :
  5385                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5386                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5387                              <1> ;	     3 - FIXED DISK						       :
  5388                              <1> ;									       :
  5389                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5390                              <1> ;									       :
  5391                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5392                              <1> ;	INFORMATION.							       :
  5393                              <1> ;									       :
  5394                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5395                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5396                              <1> ;									       :
  5397                              <1> ;-------------------------------------------------------------------------------
  5398                              <1> 
  5399                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5400                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5401                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5402                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5403                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5404                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5405                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5406                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5407                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5408                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5409                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5410                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5411                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5412                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5413                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5414                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5415                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5416                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5417                              <1> 
  5418                              <1> ;--------------------------------------------------------
  5419                              <1> ;							:
  5420                              <1> ; FIXED DISK PARAMETER TABLE				:
  5421                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5422                              <1> ;							:
  5423                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5424                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5425                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5426                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5427                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5428                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5429                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5430                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5431                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5432                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5433                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5434                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5435                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5436                              <1> ;							:
  5437                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5438                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5439                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5440                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5441                              <1> ;							:
  5442                              <1> ;--------------------------------------------------------
  5443                              <1> 
  5444                              <1> ;--------------------------------------------------------
  5445                              <1> ;							:
  5446                              <1> ; HARDWARE SPECIFIC VALUES				:
  5447                              <1> ;							:
  5448                              <1> ;  -  CONTROLLER I/O PORT				:
  5449                              <1> ;							:
  5450                              <1> ;     > WHEN READ FROM: 				:
  5451                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5452                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5453                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5454                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5455                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5456                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5457                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5458                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5459                              <1> ;							:
  5460                              <1> ;     > WHEN WRITTEN TO:				:
  5461                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5462                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5463                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5464                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5465                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5466                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5467                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5468                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5469                              <1> ;							:
  5470                              <1> ;--------------------------------------------------------
  5471                              <1> 
  5472                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5473                              <1> ;HF1_PORT	equ	0170h	
  5474                              <1> ;HF_REG_PORT	EQU	03F6H
  5475                              <1> ;HF1_REG_PORT	equ	0376h
  5476                              <1> 
  5477                              <1> HDC1_BASEPORT	equ	1F0h
  5478                              <1> HDC2_BASEPORT	equ	170h		
  5479                              <1> 
  5480                              <1> align 2
  5481                              <1> 
  5482                              <1> ;-----		STATUS REGISTER
  5483                              <1> 
  5484                              <1> ST_ERROR	EQU	00000001B	;
  5485                              <1> ST_INDEX	EQU	00000010B	;
  5486                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5487                              <1> ST_DRQ		EQU	00001000B	;
  5488                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5489                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5490                              <1> ST_READY	EQU	01000000B	;
  5491                              <1> ST_BUSY 	EQU	10000000B	;
  5492                              <1> 
  5493                              <1> ;-----		ERROR REGISTER
  5494                              <1> 
  5495                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5496                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5497                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5498                              <1> ;		EQU	00001000B	; NOT USED
  5499                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5500                              <1> ;		EQU	00100000B	; NOT USED
  5501                              <1> ERR_DATA_ECC	EQU	01000000B
  5502                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5503                              <1> 
  5504                              <1> 
  5505                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5506                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5507                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5508                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5509                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5510                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5511                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5512                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5513                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5514                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5515                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5516                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5517                              <1> 
  5518                              <1> ;MAX_FILE	EQU	2
  5519                              <1> ;S_MAX_FILE	EQU	2
  5520                              <1> MAX_FILE	equ	4		; 22/12/2014
  5521                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5522                              <1> 
  5523                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5524                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5525                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5526                              <1> 
  5527                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5528                              <1> 
  5529                              <1> ;-----		COMMAND BLOCK REFERENCE
  5530                              <1> 
  5531                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5532                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5533                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5534                              <1> ; 19/12/2014
  5535                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5536                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5537                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5538                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5539                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5540                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5541                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5542                              <1> 
  5543                              <1> align 2
  5544                              <1> 
  5545                              <1> ;----------------------------------------------------------------
  5546                              <1> ; FIXED DISK I/O SETUP						:
  5547                              <1> ;								:
  5548                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5549                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5550                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5551                              <1> ;								:
  5552                              <1> ;----------------------------------------------------------------
  5553                              <1> 
  5554                              <1> DISK_SETUP:
  5555                              <1> 	;CLI
  5556                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5557                              <1> 	;xor	ax,ax
  5558                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5559                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5560                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5561                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5562                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5563                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5564                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5565                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5566                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5567                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5568                              <1> 	;;MOV	[HDISK_INT+2],CS
  5569                              <1> 	;mov	[HDISK_INT1+2],CS
  5570                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5571                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5572                              <1> 	;mov	[HDISK_INT2+2],CS
  5573                              <1> 	;
  5574                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5575                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5576                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5577                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5578                              <1> 	;push	cs
  5579                              <1> 	;pop	ds
  5580                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5581                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5582 00002656 C705[446E0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5582 0000265E 0900                <1>
  5583                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5584                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5585 00002660 C705[486E0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5585 00002668 0900                <1>
  5586                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5587                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5588 0000266A C705[4C6E0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5588 00002672 0900                <1>
  5589                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5590                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5591 00002674 C705[506E0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5591 0000267C 0900                <1>
  5592                              <1> 	;
  5593                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5594                              <1> 	;;;AND	AL,0BFH
  5595                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5596                              <1> 	;;;JMP	$+2
  5597                              <1> 	;;IODELAY
  5598                              <1> 	;;OUT	INTB01,AL
  5599                              <1> 	;;IODELAY
  5600                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5601                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5602                              <1> 	;;;JMP	$+2
  5603                              <1> 	;;IODELAY
  5604                              <1> 	;;OUT	INTA01,AL
  5605                              <1> 	;
  5606                              <1> 	;STI
  5607                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5608                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5609                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5610                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5611                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5612                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5613                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5614                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5615                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5616                              <1> 	;mov	si, hd0_type
  5617 0000267E BE[A0680000]        <1> 	mov	esi, hd0_type
  5618                              <1> 	;mov	cx, 4
  5619 00002683 B904000000          <1> 	mov	ecx, 4
  5620                              <1> hde_l:
  5621 00002688 AC                  <1> 	lodsb
  5622 00002689 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5623 0000268B 7206                <1> 	jb	short _L4
  5624 0000268D FE05[406E0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5625                              <1> _L4: ; 26/02/2015
  5626 00002693 E2F3                <1> 	loop	hde_l	
  5627                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5628                              <1> ;L4:
  5629                              <1> 	; 
  5630                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5631                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5632                              <1> 	;;mov 	cl, 3
  5633                              <1> 	;;
  5634                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5635                              <1> ;;hdc_dl:
  5636                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5637                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5638                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5639                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5640                              <1> 	;;jnc	short hdc_reset0
  5641                              <1> 	;;loop	hdc_dl
  5642                              <1> 	;;; 27/12/2014
  5643                              <1> 	;;stc
  5644                              <1> 	;;retn
  5645                              <1> 	;
  5646                              <1> ;;hdc_reset0:
  5647                              <1> 	; 18/01/2015
  5648 00002695 8A0D[406E0000]      <1> 	mov	cl, [HF_NUM]
  5649 0000269B 20C9                <1> 	and	cl, cl
  5650 0000269D 740D                <1> 	jz	short POD_DONE
  5651                              <1> 	;
  5652 0000269F B27F                <1> 	mov	dl, 7Fh
  5653                              <1> hdc_reset1:
  5654 000026A1 FEC2                <1> 	inc	dl
  5655                              <1> 	;; 31/12/2015
  5656                              <1> 	;;push	dx
  5657                              <1> 	;;push	cx
  5658                              <1> 	;;push	ds
  5659                              <1> 	;;sub	ax, ax
  5660                              <1> 	;;mov	ds, ax
  5661                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5662                              <1> 	;;pop	ds
  5663                              <1> 	;;MOV	BX,AX
  5664                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5665                              <1> 	;;MOV	CX,AX
  5666                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5667                              <1> 	;;
  5668                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5669                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5670                              <1> 	;;pop	cx
  5671                              <1> 	;;pop	dx
  5672                              <1> 	;;
  5673                              <1> 	; 18/01/2015
  5674 000026A3 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5675                              <1> 	;int	13h
  5676 000026A5 E8A4FFFFFF          <1> 	call	int13h
  5677 000026AA E2F5                <1> 	loop	hdc_reset1
  5678                              <1> POD_DONE:
  5679 000026AC C3                  <1> 	RETn
  5680                              <1> 
  5681                              <1> ;;-----	POD_ERROR
  5682                              <1> 
  5683                              <1> ;;CTL_ERRX:
  5684                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5685                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5686                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5687                              <1> ;	;JMP	short POD_DONE
  5688                              <1> 
  5689                              <1> ;;HD_RESET_1:
  5690                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5691                              <1> ;;	;PUSH	CX
  5692                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5693                              <1> ;;	INT	13H
  5694                              <1> ;;	JC	short RES_2
  5695                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5696                              <1> ;;	INT	13H
  5697                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5698                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5699                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5700                              <1> ;;					; (30 seconds)		
  5701                              <1> ;;	;cmc
  5702                              <1> ;;	;JNC	short RES_1
  5703                              <1> ;;	jb	short RES_1
  5704                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5705                              <1> ;;	;TEST	DL,1
  5706                              <1> ;;	;JNZ	RES_E1
  5707                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5708                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5709                              <1> ;;	;JMP	SHORT RES_E1
  5710                              <1> ;;RES_ER: ; 22/12/2014
  5711                              <1> ;;RES_OK:
  5712                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5713                              <1> ;;	;POP	BX
  5714                              <1> ;;	RETn
  5715                              <1> ;;
  5716                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5717                              <1> ;;	INT	13H
  5718                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5719                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5720                              <1> ;;	INT	13H
  5721                              <1> ;;	JC	short RES_ER
  5722                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5723                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5724                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5725                              <1> ;;	INT	13H
  5726                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5727                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5728                              <1> ;;	JE	short RES_OK
  5729                              <1> ;;	CMP	AH,DATA_CORRECTED
  5730                              <1> ;;	JE	short RES_OK
  5731                              <1> ;;	CMP	AH,BAD_ECC
  5732                              <1> ;;	JE	short RES_OK
  5733                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5734                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5735                              <1> ;;					; (60 seconds)		
  5736                              <1> ;;	cmc
  5737                              <1> ;;	JC	short RES_ER		; FAILED
  5738                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5739                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5740                              <1> ;;	AND	AL,3FH
  5741                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5742                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5743                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5744                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5745                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5746                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5747                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5748                              <1> ;;	;TEST	DL,1
  5749                              <1> ;;	;JNZ	short RES_E1
  5750                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5751                              <1> ;;;RES_E1:
  5752                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5753                              <1> ;;;RES_OK:
  5754                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5755                              <1> ;;	;POP	BX
  5756                              <1> ;;	;RETn
  5757                              <1> ;
  5758                              <1> ;;SET_FAIL:
  5759                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5760                              <1> ;	;CALL	CMOS_READ
  5761                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5762                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5763                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5764                              <1> ;	;RETn
  5765                              <1> ;
  5766                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5767                              <1> ;	;POP	AX			; SAVE RETURN
  5768                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5769                              <1> ;	;POP	BX
  5770                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5771                              <1> ;	;PUSH	CX
  5772                              <1> ;	;PUSH	AX
  5773                              <1> ;	;push	ds
  5774                              <1> ;	;xor	ax, ax
  5775                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5776                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5777                              <1> ;	;				; BX = START TIME
  5778                              <1> ;	;				; CX = END TIME
  5779                              <1> ;	;pop	ds
  5780                              <1> ;	;CMP	BX,CX
  5781                              <1> ;	;JB	short TCHK1		; START < END
  5782                              <1> ;	;CMP	BX,AX
  5783                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5784                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5785                              <1> ;;TCHK1: CMP	AX,BX
  5786                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5787                              <1> ;;TCHK2: CMP	AX,CX
  5788                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5789                              <1> ;;					; OR CURRENT < END < START
  5790                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5791                              <1> ;;	RETn
  5792                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5793                              <1> ;;	RETn
  5794                              <1> ;;
  5795                              <1> ;;int_13h:
  5796                              <1> 
  5797                              <1> ;----------------------------------------
  5798                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5799                              <1> ;----------------------------------------
  5800                              <1> 
  5801                              <1> DISK_IO:
  5802 000026AD 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5803                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5804                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5805                              <1> 	;;call	int40h
  5806                              <1> 	;jb	DISKETTE_IO_1
  5807                              <1> 	; 05/12/2021
  5808 000026B0 7305                <1> 	jnb	short A1
  5809 000026B2 E960F1FFFF          <1> 	jmp	DISKETTE_IO_1
  5810                              <1> ;RET_2:
  5811                              <1> 	;RETf	2			; BACK TO CALLER
  5812                              <1> ;	retf	4
  5813                              <1> A1:
  5814 000026B7 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5815                              <1> 	;; 04/01/2015
  5816                              <1> 	;;OR	AH,AH
  5817                              <1> 	;;JNZ	short A2
  5818                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5819                              <1> 	;;SUB	AH,AH
  5820 000026B8 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5821 000026BB 772E                <1> 	JA	short RET_2
  5822                              <1> 	; 18/01/2015
  5823 000026BD 08E4                <1> 	or	ah,ah
  5824 000026BF 742D                <1> 	jz	short A4
  5825 000026C1 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5826 000026C4 7504                <1> 	jne	short A2
  5827 000026C6 28E4                <1> 	sub	ah,ah	; Reset
  5828 000026C8 EB24                <1> 	jmp	short A4
  5829                              <1> A2:
  5830 000026CA 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5831                              <1> 	;JNZ	short A3
  5832                              <1>         ;JMP    GET_PARM_N
  5833                              <1> 	;je	GET_PARM_N
  5834                              <1> 	; 05/12/2021
  5835 000026CD 7505                <1> 	jne	short A3
  5836 000026CF E90D030000          <1> 	jmp	GET_PARM_N
  5837                              <1> A3:	
  5838 000026D4 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5839                              <1> 	;JNZ	short A4
  5840                              <1>         ;JMP    READ_DASD_TYPE
  5841                              <1> 	;je	READ_DASD_TYPE
  5842                              <1> 	; 05/12/2021
  5843 000026D7 7505                <1> 	jne	short A3_A4
  5844 000026D9 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5845                              <1> A3_A4:
  5846                              <1> 	; 02/02/2015
  5847 000026DE 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5848                              <1> 	; 12/01/2015
  5849 000026E1 F5                  <1> 	cmc
  5850 000026E2 730A                <1> 	jnc	short A4
  5851                              <1> 	; 30/01/2015
  5852                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5853 000026E4 C605[3F6E0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5854                              <1> 	;jmp	short RET_2
  5855                              <1> RET_2:
  5856 000026EB CA0400              <1> 	retf	4
  5857                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5858 000026EE C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5859 000026F2 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5860 000026F3 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5861 000026F4 52                  <1> 	PUSH	eDX
  5862 000026F5 1E                  <1> 	PUSH	DS
  5863 000026F6 06                  <1> 	PUSH	ES
  5864 000026F7 56                  <1> 	PUSH	eSI
  5865 000026F8 57                  <1> 	PUSH	eDI
  5866                              <1> 	;;04/01/2015
  5867                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5868                              <1> 	;;JNZ	short A5
  5869                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5870                              <1> ;;A5:	
  5871                              <1> 	;push	cs
  5872                              <1> 	;pop	ds
  5873                              <1> 	; 21/02/2015
  5874                              <1> 	;push	ax
  5875                              <1> 	; 05/12/2021
  5876 000026F9 50                  <1> 	push	eax
  5877 000026FA 66B81000            <1> 	mov	ax, KDATA
  5878 000026FE 8ED8                <1> 	mov	ds, ax
  5879 00002700 8EC0                <1> 	mov	es, ax	
  5880                              <1> 	;pop	ax
  5881                              <1> 	; 05/12/2021
  5882 00002702 58                  <1> 	pop	eax
  5883 00002703 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5884                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5885 00002708 8A25[3F6E0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5886 0000270E 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5887 00002711 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5888 00002712 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5889 00002713 5E                  <1> 	POP	eSI
  5890 00002714 07                  <1>         POP     ES
  5891 00002715 1F                  <1>         POP     DS
  5892 00002716 5A                  <1> 	POP	eDX
  5893 00002717 59                  <1> 	POP	eCX
  5894 00002718 5B                  <1> 	POP	eBX
  5895 00002719 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5896                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5897 0000271A CA0400              <1> 	retf	4
  5898                              <1> ; 21/02/2015
  5899                              <1> ;       dw --> dd
  5900                              <1> M1:					; FUNCTION TRANSFER TABLE
  5901 0000271D [D6280000]          <1> 	dd	DISK_RESET		; 000H
  5902 00002721 [4B290000]          <1> 	dd	RETURN_STATUS		; 001H
  5903 00002725 [58290000]          <1> 	dd	DISK_READ		; 002H
  5904 00002729 [61290000]          <1> 	dd	DISK_WRITE		; 003H
  5905 0000272D [6A290000]          <1> 	dd	DISK_VERF		; 004H
  5906 00002731 [82290000]          <1> 	dd	FMT_TRK 		; 005H
  5907 00002735 [CC280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5908 00002739 [CC280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5909 0000273D [CC280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5910 00002741 [432A0000]          <1> 	dd	INIT_DRV		; 009H
  5911 00002745 [A22A0000]          <1> 	dd	RD_LONG 		; 00AH
  5912 00002749 [AB2A0000]          <1> 	dd	WR_LONG 		; 00BH
  5913 0000274D [B42A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5914 00002751 [D6280000]          <1> 	dd	DISK_RESET		; 00DH
  5915 00002755 [CC280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5916 00002759 [CC280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5917 0000275D [DC2A0000]          <1> 	dd	TST_RDY 		; 010H
  5918 00002761 [002B0000]          <1> 	dd	HDISK_RECAL		; 011H
  5919 00002765 [CC280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5920 00002769 [CC280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5921 0000276D [362B0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5922                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5923 00002771 [CC280000]          <1> 	dd	BAD_COMMAND		; 015h
  5924 00002775 [CC280000]          <1> 	dd	BAD_COMMAND		; 016h
  5925 00002779 [CC280000]          <1> 	dd	BAD_COMMAND		; 017h
  5926 0000277D [CC280000]          <1> 	dd	BAD_COMMAND		; 018h
  5927 00002781 [CC280000]          <1> 	dd	BAD_COMMAND		; 019h
  5928 00002785 [CC280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5929 00002789 [58290000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5930 0000278D [61290000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5931                              <1> M1L     EQU    $-M1
  5932                              <1> 
  5933                              <1> DISK_IO_CONT:
  5934                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5935 00002791 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5936                              <1> 	;;JNZ	short SU0
  5937                              <1>         ;;JMP	RETURN_STATUS
  5938                              <1> 	;je	RETURN_STATUS
  5939                              <1> 	; 05/12/2021
  5940 00002794 7505                <1> 	jne	short SU0
  5941 00002796 E9B0010000          <1> 	jmp	RETURN_STATUS
  5942                              <1> SU0:
  5943 0000279B C605[3F6E0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5944                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5945                              <1> 	;mov	si, bx ;; 14/02/2015
  5946 000027A2 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5947 000027A4 8A1D[406E0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5948                              <1> 	;; 04/01/2015
  5949                              <1> 	;;PUSH	AX
  5950 000027AA 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5951                              <1> 					; (get drive number as 0 to 3)
  5952 000027AD 38D3                <1> 	CMP	BL,DL
  5953                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5954                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5955                              <1> 	; 05/12/2021
  5956 000027AF 7705                <1> 	ja	short su0_su1
  5957 000027B1 E916010000          <1> 	jmp	BAD_COMMAND
  5958                              <1> su0_su1:
  5959                              <1>         ;;03/01/2015
  5960 000027B6 29DB                <1> 	sub	ebx, ebx
  5961 000027B8 88D3                <1> 	mov	bl, dl
  5962                              <1> 	;sub	bh, bh
  5963 000027BA 883D[546E0000]      <1> 	mov	[LBAMode], bh 	; 0
  5964                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5965                              <1> 	;test	byte [ebx+hd0_type], 1
  5966                              <1> 	;jz	short su1		; no
  5967                              <1> 	;inc	byte [LBAMode]
  5968                              <1> ;su1:
  5969                              <1> 	; 21/02/2015 (32 bit modification)
  5970                              <1> 	; 04/01/2015
  5971                              <1> 	;push	ax ; ***
  5972                              <1> 	; 05/12/2021
  5973 000027C0 50                  <1> 	push	eax ; ***
  5974                              <1> 	;PUSH	ES ; **
  5975                              <1> 	;PUSH	DX ; *
  5976                              <1> 	; 05/12/2021
  5977 000027C1 52                  <1> 	push	edx ; *
  5978                              <1> 	;push	ax
  5979 000027C2 50                  <1> 	push	eax
  5980 000027C3 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5981                              <1> 	; 02/02/2015
  5982                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5983 000027C8 668B4310            <1> 	mov	ax, [ebx+16]
  5984 000027CC 66A3[94680000]      <1> 	mov	[HF_PORT], ax
  5985                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5986 000027D2 668B5312            <1> 	mov	dx, [ebx+18]
  5987 000027D6 668915[96680000]    <1> 	mov	[HF_REG_PORT], dx
  5988                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5989 000027DD 8A4314              <1> 	mov	al, [ebx+20]
  5990                              <1> 	; 23/02/2015
  5991 000027E0 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5992 000027E2 7406                <1> 	jz 	short su1
  5993 000027E4 FE05[546E0000]      <1> 	inc	byte [LBAMode] ; 1 
  5994                              <1> su1: 	 
  5995 000027EA C0E804              <1> 	shr 	al, 4
  5996 000027ED 2401                <1> 	and	al, 1			
  5997 000027EF A2[98680000]        <1> 	mov	[hf_m_s], al 
  5998                              <1> 	;
  5999                              <1> 	; 03/01/2015
  6000                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  6001 000027F4 8A4308              <1> 	mov	al, [ebx+8]
  6002                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  6003 000027F7 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  6004                              <1> 					; Control Byte:  (= 08h, here)
  6005                              <1> 					; bit 0 - 0
  6006                              <1> 					; bit 1 - nIEN (1 = disable irq)
  6007                              <1> 					; bit 2 - SRST (software RESET)
  6008                              <1> 					; bit 3 - use extra heads (8 to 15)
  6009                              <1> 					;         -always set to 1-	
  6010                              <1> 					; (bits 3 to 7 are reserved
  6011                              <1> 					;          for ATA devices)
  6012 000027F8 8A25[416E0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6013 000027FE 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  6014 00002801 08C4                <1> 	OR	AH,AL
  6015 00002803 8825[416E0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  6016                              <1> 	; 04/01/2015
  6017                              <1> 	;pop	ax
  6018                              <1> 	; 05/12/2021
  6019 00002809 58                  <1> 	pop	eax
  6020                              <1> 	;pop	dx ; * ;; 14/02/2015
  6021                              <1> 	; 05/12/2021
  6022 0000280A 5A                  <1> 	pop	edx ; *
  6023 0000280B 20E4                <1> 	and	ah, ah	; Reset function ?
  6024 0000280D 7506                <1> 	jnz	short su2
  6025                              <1> 	;;pop	dx ; * ;; 14/02/2015
  6026                              <1> 	;pop	es ; **
  6027                              <1> 	;pop	ax ; ***
  6028                              <1> 	; 05/12/2021
  6029 0000280F 58                  <1> 	pop	eax ; ***	
  6030                              <1> 	;;pop	bx
  6031 00002810 E9C1000000          <1>         jmp     DISK_RESET
  6032                              <1> su2:
  6033 00002815 803D[546E0000]00    <1> 	cmp	byte [LBAMode], 0
  6034 0000281C 765E                <1> 	jna	short su3
  6035                              <1> 	;
  6036                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6037 0000281E 80FC1B              <1> 	cmp	ah, 1Bh
  6038 00002821 720B                <1> 	jb	short lbarw1
  6039 00002823 80FC1C              <1> 	cmp	ah, 1Ch
  6040 00002826 7759                <1> 	ja 	short invldfnc
  6041                              <1> 	;;pop	dx ; * ; 14/02/2015
  6042                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6043 00002828 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6044                              <1> 	;; 14/02/2015
  6045 0000282A 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6046                              <1> 	;;mov	dx, bx
  6047                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6048                              <1> 	;;mov	bx, di
  6049                              <1> 	;mov	si, di ; Buffer offset
  6050 0000282C EB2E                <1> 	jmp	short lbarw2
  6051                              <1> lbarw1:
  6052                              <1> 	; convert CHS to LBA
  6053                              <1> 	;
  6054                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6055                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6056                              <1> 	;	+ Sector - 1
  6057                              <1> 	;push	dx ; * ;; 14/02/2015
  6058                              <1> 	; 05/12/2021
  6059 0000282E 52                  <1> 	push	edx ; *
  6060                              <1> 	;xor	dh, dh
  6061 0000282F 31D2                <1> 	xor	edx, edx
  6062                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6063 00002831 8A530E              <1> 	mov	dl, [ebx+14]
  6064                              <1> 	;xor	ah, ah
  6065 00002834 31C0                <1> 	xor	eax, eax
  6066                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6067 00002836 8A4302              <1> 	mov	al, [ebx+2]
  6068 00002839 FEC8                <1> 	dec	al
  6069                              <1> 	;inc	ax		; 0 =  256
  6070 0000283B 40                  <1> 	inc	eax ; 05/12/2021
  6071 0000283C 66F7E2              <1> 	mul 	dx
  6072                              <1> 		; AX = # of Heads" * Sectors/Track
  6073 0000283F 6689CA              <1> 	mov	dx, cx
  6074                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6075 00002842 83E13F              <1> 	and	ecx, 3fh
  6076 00002845 86D6                <1> 	xchg	dl, dh
  6077 00002847 C0EE06              <1> 	shr	dh, 6
  6078                              <1> 		; DX = cylinder (0 to 1023)
  6079                              <1> 	;mul 	dx
  6080                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6081 0000284A F7E2                <1> 	mul	edx
  6082 0000284C FEC9                <1> 	dec	cl  ; sector - 1
  6083                              <1> 	;add	ax, cx
  6084                              <1> 	;adc	dx, 0
  6085                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6086 0000284E 01C8                <1> 	add	eax, ecx
  6087                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6088                              <1> 	; 05/12/2021
  6089 00002850 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6090                              <1> 	;push	dx
  6091                              <1> 	;push	ax
  6092 00002851 50                  <1> 	push	eax
  6093                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6094 00002852 8A430E              <1> 	mov	al, [ebx+14]
  6095 00002855 F6E5                <1> 	mul	ch
  6096                              <1> 		; AX = Head * Sectors/Track
  6097 00002857 6699                <1>         cwd
  6098                              <1> 	;pop	dx
  6099 00002859 5A                  <1> 	pop	edx
  6100                              <1> 	;add	ax, dx
  6101                              <1> 	;pop	dx
  6102                              <1> 	;adc	dx, 0 ; add carry bit
  6103 0000285A 01D0                <1> 	add	eax, edx
  6104                              <1> lbarw2:
  6105 0000285C 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6106 0000285E 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6107 00002860 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6108                              <1> 				; NOTE: Features register (1F1h, 171h)
  6109                              <1> 				; is not used for ATA device R/W functions. 
  6110                              <1> 				; It is old/obsolete 'write precompensation'
  6111                              <1> 				; register and error register
  6112                              <1> 				; for old ATA/IDE devices.
  6113                              <1> 	; 18/01/2014
  6114                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6115 00002864 8A0D[98680000]      <1> 	mov	cl, [hf_m_s]
  6116                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6117                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6118                              <1> 				; bit 6 = 1 = LBA mode
  6119                              <1> 				; bit 7 = 1
  6120 0000286A 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6121                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6122 0000286D 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6123 00002872 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6124                              <1> 	;or	dh, ch
  6125 00002875 09C8                <1> 	or	eax, ecx	
  6126                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6127                              <1> 				  ; (Sector Number Register)
  6128                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6129                              <1> 				  ; (Cylinder Low Register)
  6130                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6131                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6132                              <1> 				  ; (Cylinder High Register)
  6133                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6134                              <1> 				  ; (Drive/Head Register)
  6135                              <1> 	
  6136                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6137 00002877 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6138                              <1> 	;14/02/2015
  6139                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6140 0000287A EB37                <1> 	jmp	short su4
  6141                              <1> su3:
  6142                              <1> 	; 02/02/2015 
  6143                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6144 0000287C 80FC14              <1> 	cmp 	ah, 14h
  6145 0000287F 7603                <1> 	jna 	short chsfnc
  6146                              <1> invldfnc:
  6147                              <1>         ; 14/02/2015  
  6148                              <1> 	;pop	es ; **
  6149                              <1>         ;pop	ax ; ***
  6150                              <1>         ; 05/12/2021
  6151 00002881 58                  <1> 	pop	eax ; ***
  6152                              <1> 	;jmp	short BAD_COMMAND_POP
  6153 00002882 EB48                <1>         jmp     short BAD_COMMAND
  6154                              <1> chsfnc:	
  6155                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6156 00002884 668B4305            <1> 	mov	ax, [ebx+5]
  6157 00002888 66C1E802            <1> 	SHR	AX,2
  6158 0000288C 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6159                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6160                              <1> 	;;PUSH	DX
  6161                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6162                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6163                              <1> 	;;POP	DX ; * 
  6164                              <1> 	;;POP	ES ; **
  6165                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6166                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6167                              <1> 	;;OR	AH,AL
  6168                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6169                              <1> 	;
  6170 0000288F 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6171 00002891 243F                <1> 	AND	AL,3FH
  6172 00002893 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6173 00002896 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6174 00002899 88C8                <1> 	MOV	AL,CL
  6175 0000289B C0E806              <1> 	SHR	AL,6
  6176 0000289E 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6177                              <1> 	;;05/01/2015
  6178                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6179 000028A1 A0[98680000]        <1> 	mov	al, [hf_m_s]
  6180 000028A6 C0E004              <1> 	SHL	AL,4
  6181 000028A9 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6182 000028AC 08F0                <1> 	OR	AL,DH
  6183                              <1> 	;OR	AL,80H or 20H
  6184 000028AE 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6185 000028B0 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6186                              <1> su4:
  6187                              <1> 	;POP	ES ; **
  6188                              <1>         ;; 14/02/2015
  6189                              <1>         ;;POP   AX
  6190                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6191                              <1>         ;;PUSH  AX
  6192                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6193                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6194                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6195                              <1> 	;pop	ax ; ***
  6196                              <1> 	; 05/12/2021
  6197 000028B3 58                  <1> 	pop	eax ; ***
  6198 000028B4 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6199 000028B7 29DB                <1>         sub	ebx, ebx
  6200 000028B9 88E3                <1> 	mov     bl, ah
  6201                              <1>         ;xor	bh, bh
  6202                              <1>         ;sal	bx, 1
  6203 000028BB 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6204                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6205                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6206                              <1>         ;;JNB   short BAD_COMMAND_POP
  6207                              <1>         ;cmp	bx, M1L
  6208 000028BF 83FB74              <1> 	cmp	ebx, M1L
  6209 000028C2 7308                <1> 	jnb	short BAD_COMMAND
  6210                              <1>         ;xchg	bx, si
  6211 000028C4 87DE                <1>         xchg	ebx, esi
  6212                              <1> 	;;;POP	AX			; RESTORE AX
  6213                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6214                              <1> 	
  6215                              <1> 	;;PUSH	CX
  6216                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6217                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6218                              <1> 	;SHR	CX,4
  6219                              <1> 	;MOV	AX,ES
  6220                              <1> 	;ADD	AX,CX
  6221                              <1> 	;MOV	ES,AX
  6222                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6223                              <1> 	;;POP	AX
  6224                              <1> 	;;POP	CX
  6225                              <1> 	;;JMP	word [CS:SI+M1]
  6226                              <1> 	;jmp	word [SI+M1]
  6227 000028C6 FFA6[1D270000]      <1> 	jmp	dword [esi+M1]
  6228                              <1> ;;BAD_COMMAND_POP:
  6229                              <1> ;;	POP	AX
  6230                              <1> ;;	POP	BX
  6231                              <1> BAD_COMMAND:
  6232 000028CC C605[3F6E0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6233 000028D3 B000                <1> 	MOV	AL,0
  6234 000028D5 C3                  <1> 	RETn
  6235                              <1> 
  6236                              <1> ;----------------------------------------
  6237                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6238                              <1> ;----------------------------------------
  6239                              <1> 
  6240                              <1> ; 18-1-2015 : one controller reset (not other one)
  6241                              <1> 
  6242                              <1> DISK_RESET:
  6243 000028D6 FA                  <1> 	CLI
  6244 000028D7 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6245                              <1> 	;JMP	$+2
  6246                              <1> 	IODELAY
  2133 000028D9 EB00                <2>  jmp short $+2
  2134 000028DB EB00                <2>  jmp short $+2
  6247                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6248 000028DD 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6249 000028DF E6A1                <1> 	OUT	INTB01,AL
  6250 000028E1 FB                  <1> 	STI				; START INTERRUPTS
  6251                              <1> 	; 14/02/2015
  6252                              <1> 	;mov	di, dx
  6253                              <1> 	; 05/12/2021
  6254 000028E2 89D7                <1> 	mov	edi, edx	
  6255                              <1> 	; 04/01/2015
  6256                              <1> 	;xor	di,di
  6257                              <1> drst0:
  6258 000028E4 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6259                              <1> 	;MOV	DX,HF_REG_PORT
  6260 000028E6 668B15[96680000]    <1> 	MOV	DX,[HF_REG_PORT]
  6261 000028ED EE                  <1> 	OUT	DX,AL			; RESET
  6262                              <1> ;	MOV	CX,10			; DELAY COUNT
  6263                              <1> ;DRD:	DEC	CX
  6264                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6265                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6266 000028EE B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6267 000028F3 E8D3EBFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6268                              <1>                                         ; 40 micro seconds)
  6269 000028F8 A0[416E0000]        <1> 	mov	al,[CONTROL_BYTE]
  6270 000028FD 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6271 000028FF EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6272 00002900 E807040000          <1> 	CALL	NOT_BUSY
  6273 00002905 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6274 00002907 668B15[94680000]    <1> 	MOV	DX,[HF_PORT]
  6275 0000290E FEC2                <1> 	inc	dl  ; HF_PORT+1
  6276                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6277                              <1>         ;mov	cl, 10
  6278 00002910 B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6279                              <1> drst1:
  6280 00002915 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6281 00002916 3C01                <1> 	CMP	AL,1
  6282                              <1> 	; 04/01/2015
  6283 00002918 740A                <1> 	jz	short drst2
  6284                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6285                              <1>         	; Drive/Head Register - bit 4
  6286 0000291A E2F9                <1> 	loop	drst1
  6287                              <1> DRERR:	
  6288 0000291C C605[3F6E0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6289 00002923 C3                  <1> 	RETn
  6290                              <1> drst2:
  6291                              <1> 	; 14/02/2015
  6292                              <1> 	;mov	dx, di
  6293                              <1> 	; 05/12/2021
  6294 00002924 89FA                <1> 	mov	edx, edi
  6295                              <1> ;drst3:
  6296                              <1> ;	; 05/01/2015
  6297                              <1> ;	shl 	di,1
  6298                              <1> ;	; 04/01/2015
  6299                              <1> ;	mov	ax,[di+hd_cports]
  6300                              <1> ;	cmp	ax,[HF_REG_PORT]
  6301                              <1> ;	je	short drst4
  6302                              <1> ;	mov	[HF_REG_PORT], ax
  6303                              <1> ;	; 03/01/2015
  6304                              <1> ;	mov	ax,[di+hd_ports]
  6305                              <1> ;       mov     [HF_PORT], ax
  6306                              <1> ;	; 05/01/2014
  6307                              <1> ;	shr	di,1
  6308                              <1> ;	; 04/01/2015
  6309                              <1> ;	jmp	short drst0	; reset other controller
  6310                              <1> ;drst4:
  6311                              <1> ;	; 05/01/2015
  6312                              <1> ;	shr	di,1
  6313                              <1> ;	mov	al,[di+hd_dregs]
  6314                              <1> ;	and	al,10h ; bit 4 only
  6315                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6316                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6317                              <1> 	;
  6318 00002926 A0[98680000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6319 0000292B A801                <1> 	test	al,1
  6320                              <1> ;	jnz	short drst6
  6321 0000292D 7516                <1>         jnz     short drst4
  6322 0000292F 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6323                              <1> ;drst5:
  6324                              <1> drst3:
  6325 00002933 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6326                              <1> 	;mov	dx,di
  6327 00002938 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6328                              <1> 	; 04/01/2014
  6329                              <1> ;	inc	di
  6330                              <1> ;	mov	dx,di
  6331                              <1> ;	cmp	dl,[HF_NUM]
  6332                              <1> ;	jb	short drst3
  6333                              <1> ;DRE:
  6334 0000293D C605[3F6E0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6335 00002944 C3                  <1> 	RETn
  6336                              <1> ;drst6:
  6337                              <1> drst4:		; Drive/Head Register - bit 4
  6338 00002945 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6339                              <1>         ;jmp    short drst5
  6340 00002949 EBE8                <1>         jmp     short drst3
  6341                              <1> 
  6342                              <1> ;----------------------------------------
  6343                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6344                              <1> ;----------------------------------------
  6345                              <1> 
  6346                              <1> RETURN_STATUS:
  6347 0000294B A0[3F6E0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6348 00002950 C605[3F6E0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6349 00002957 C3                  <1> 	RETn
  6350                              <1> 
  6351                              <1> ;----------------------------------------
  6352                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6353                              <1> ;----------------------------------------
  6354                              <1> 
  6355                              <1> DISK_READ:
  6356 00002958 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6357 0000295C E92A020000          <1>         JMP     COMMANDI
  6358                              <1> 
  6359                              <1> ;----------------------------------------
  6360                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6361                              <1> ;----------------------------------------
  6362                              <1> 
  6363                              <1> DISK_WRITE:
  6364 00002961 C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6365 00002965 E976020000          <1>         JMP     COMMANDO
  6366                              <1> 
  6367                              <1> ;----------------------------------------
  6368                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6369                              <1> ;----------------------------------------
  6370                              <1> 
  6371                              <1> DISK_VERF:
  6372 0000296A C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6373 0000296E E8E4020000          <1> 	CALL	COMMAND
  6374 00002973 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6375 00002975 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6376 0000297A 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6377 0000297C E8E3030000          <1> 	CALL	CHECK_STATUS
  6378                              <1> VERF_EXIT:
  6379 00002981 C3                  <1> 	RETn
  6380                              <1> 
  6381                              <1> ;----------------------------------------
  6382                              <1> ;	FORMATTING	     (AH = 05H) :
  6383                              <1> ;----------------------------------------
  6384                              <1> 
  6385                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6386 00002982 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6387                              <1> 	;PUSH	ES
  6388                              <1> 	;PUSH	BX
  6389 00002986 53                  <1> 	push	ebx
  6390 00002987 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6391                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6392 0000298C 8A430E              <1> 	mov	al, [ebx+14]
  6393 0000298F 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6394 00002992 5B                  <1> 	pop	ebx
  6395                              <1> 	;POP	BX
  6396                              <1> 	;POP	ES
  6397 00002993 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6398                              <1> 
  6399                              <1> ;----------------------------------------
  6400                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6401                              <1> ;----------------------------------------
  6402                              <1> 
  6403                              <1> READ_DASD_TYPE:
  6404                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6405 00002998 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6406                              <1> 	;PUSH	ES
  6407 00002999 53                  <1> 	PUSH	eBX
  6408                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6409                              <1> 	;push	cs
  6410                              <1> 	;pop	ds
  6411 0000299A 66BB1000            <1>         mov	bx, KDATA
  6412 0000299E 8EDB                <1> 	mov	ds, bx
  6413                              <1> 	;mov	es, bx
  6414 000029A0 C605[3F6E0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6415 000029A7 8A1D[406E0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6416 000029AD 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6417 000029B0 38D3                <1> 	CMP	BL,DL
  6418 000029B2 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6419 000029B4 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6420                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6421 000029B9 8A4302              <1> 	mov	al, [ebx+2]
  6422                              <1> 	;MOV	CL,[ES:BX+14]
  6423 000029BC 8A4B0E              <1> 	mov	cl, [ebx+14]
  6424 000029BF F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6425                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6426 000029C1 668B0B              <1> 	mov	cx, [ebx]
  6427                              <1> 	;
  6428                              <1> 	; 02/01/2015 
  6429                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6430                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6431 000029C4 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6432                              <1> 	;
  6433 000029C6 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6434 000029C9 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6435 000029CC 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6436                              <1> 	;SUB	AX,AX
  6437 000029CF 28C0                <1> 	sub	al, al
  6438 000029D1 B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6439 000029D3 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6440                              <1> 	;POP	ES
  6441 000029D4 1F                  <1> 	POP	DS
  6442 000029D5 F8                  <1> 	CLC				; CLEAR CARRY
  6443                              <1> 	;RETf	2
  6444 000029D6 CA0400              <1> 	retf	4
  6445                              <1> RDT_NOT_PRESENT:
  6446                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6447                              <1> 	; 05/12/2021
  6448 000029D9 29C0                <1> 	sub	eax, eax
  6449                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6450                              <1> 	;MOV	DX,AX
  6451 000029DB 89C1                <1> 	mov	ecx, eax
  6452 000029DD 89C2                <1> 	mov	edx, eax
  6453 000029DF EBF2                <1> 	JMP	short RDT2
  6454                              <1> 
  6455                              <1> ;----------------------------------------
  6456                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6457                              <1> ;----------------------------------------
  6458                              <1> 
  6459                              <1> GET_PARM_N:
  6460                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6461 000029E1 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6462                              <1> 	;PUSH	ES
  6463 000029E2 53                  <1> 	PUSH	eBX
  6464                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6465                              <1> 	;MOV	DS,AX
  6466                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6467                              <1> 	;JZ	short G0
  6468                              <1> 	;LES	BX,@HF1_TBL_VEC
  6469                              <1> 	;JMP	SHORT G1
  6470                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6471                              <1> ;G1:
  6472                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6473                              <1> 	; 22/12/2014
  6474                              <1> 	;push	cs
  6475                              <1> 	;pop	ds
  6476 000029E3 66BB1000            <1> 	mov	bx, KDATA
  6477 000029E7 8EDB                <1> 	mov	ds, bx
  6478                              <1> 	;mov	es, bx
  6479                              <1> 	;
  6480 000029E9 80EA80              <1> 	SUB	DL,80H
  6481 000029EC 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6482 000029EF 7340                <1> 	JAE	short G4
  6483                              <1> 	;
  6484 000029F1 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6485                              <1> 	; 22/12/2014
  6486 000029F3 88D3                <1> 	mov	bl, dl
  6487                              <1> 	;xor	bh, bh  
  6488 000029F5 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6489                              <1> 	;add	bx, HF_TBL_VEC
  6490 000029F8 81C3[446E0000]      <1> 	add	ebx, HF_TBL_VEC
  6491                              <1> 	;mov	ax, [bx+2]
  6492                              <1> 	;mov	es, ax			; dpt segment
  6493                              <1> 	;mov	bx, [bx]		; dpt offset
  6494 000029FE 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6495                              <1> 
  6496 00002A00 C605[3F6E0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6497                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6498 00002A07 668B03              <1> 	mov	ax, [ebx]
  6499                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6500 00002A0A 6648                <1> 	dec	ax			; max. cylinder number
  6501 00002A0C 88C5                <1> 	MOV	CH,AL
  6502 00002A0E 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6503 00002A12 66D1E8              <1> 	SHR	AX,1
  6504 00002A15 66D1E8              <1> 	SHR	AX,1
  6505                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6506 00002A18 0A430E              <1> 	or	al, [ebx+14]
  6507 00002A1B 88C1                <1> 	MOV	CL,AL
  6508                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6509 00002A1D 8A7302              <1> 	mov	dh, [ebx+2]
  6510 00002A20 FECE                <1> 	DEC	DH			; 0-N RANGE
  6511 00002A22 8A15[406E0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6512                              <1> 	;SUB	AX,AX
  6513                              <1> 	; 05/12/2021
  6514 00002A28 29C0                <1> 	sub	eax, eax
  6515                              <1> 	; 27/12/2014 
  6516                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6517                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6518                              <1> 	;mov	di, bx			; HDPT offset
  6519 00002A2A 89DF                <1> 	mov	edi, ebx
  6520                              <1> G5:
  6521 00002A2C 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6522                              <1> 	;POP	ES
  6523 00002A2D 1F                  <1> 	POP	DS
  6524                              <1> 	;RETf	2
  6525 00002A2E CA0400              <1> 	retf	4
  6526                              <1> G4:
  6527 00002A31 C605[3F6E0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6528                              <1> 	; 05/12/2021
  6529 00002A38 29C0                <1> 	sub	eax, eax
  6530 00002A3A B407                <1> 	MOV	AH,INIT_FAIL
  6531                              <1> 	;SUB	AL,AL
  6532                              <1> 	;SUB	DX,DX
  6533 00002A3C 29D2                <1> 	sub	edx, edx
  6534                              <1> 	;SUB	CX,CX
  6535 00002A3E 29C9                <1> 	sub	ecx, ecx
  6536 00002A40 F9                  <1> 	STC				; SET ERROR FLAG
  6537 00002A41 EBE9                <1> 	JMP	short G5
  6538                              <1> 
  6539                              <1> ;----------------------------------------
  6540                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6541                              <1> ;----------------------------------------
  6542                              <1> 	; 03/01/2015
  6543                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6544                              <1> 	; logical sector per logical track
  6545                              <1> 	; and logical heads - 1 would be set but
  6546                              <1> 	; it is seen as it will be good
  6547                              <1> 	; if physical parameters will be set here
  6548                              <1> 	; because, number of heads <= 16.
  6549                              <1> 	; (logical heads usually more than 16)
  6550                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6551                              <1> 	;	== INT 13h physical parameters
  6552                              <1> 
  6553                              <1> ;INIT_DRV:
  6554                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6555                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6556                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6557                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6558                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6559                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6560                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6561                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6562                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6563                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6564                              <1> ;	SUB	AX,AX
  6565                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6566                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6567                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6568                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6569                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6570                              <1> ;	CALL	CHECK_STATUS
  6571                              <1> ;INIT_EXIT:
  6572                              <1> ;	RETn
  6573                              <1> 
  6574                              <1> ; 04/01/2015
  6575                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6576                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6577                              <1> INIT_DRV:
  6578                              <1> 	;xor	ah,ah
  6579 00002A43 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6580 00002A45 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6581 00002A47 3825[546E0000]      <1>         cmp     [LBAMode], ah   ; 0
  6582 00002A4D 7702                <1> 	ja	short idrv0
  6583 00002A4F B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6584                              <1> idrv0:
  6585                              <1> 	; DL = drive number (0 based)
  6586 00002A51 E8BB030000          <1> 	call	GET_VEC
  6587                              <1> 	;push	bx
  6588 00002A56 53                  <1> 	push	ebx ; 21/02/2015
  6589                              <1> 	;add	bx,ax
  6590 00002A57 01C3                <1> 	add	ebx,eax
  6591                              <1> 	;; 05/01/2015
  6592 00002A59 8A25[98680000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6593                              <1> 	;;and 	ah,1 
  6594 00002A5F C0E404              <1> 	shl	ah,4
  6595 00002A62 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6596                              <1> 	;mov	al,[es:bx]
  6597 00002A65 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6598 00002A67 FEC8                <1> 	dec	al	 ; last head number 
  6599                              <1> 	;and	al,0Fh
  6600 00002A69 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6601                              <1> 	;
  6602 00002A6B C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6603 00002A6F 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6604                              <1> 	;pop	bx
  6605 00002A72 5B                  <1> 	pop	ebx
  6606 00002A73 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6607 00002A75 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6608 00002A77 803D[546E0000]00    <1> 	cmp	byte [LBAMode],0
  6609 00002A7E 7702                <1> 	ja	short idrv1
  6610 00002A80 B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6611                              <1> idrv1:
  6612                              <1> 	;xor	ah,ah
  6613                              <1> 	;add	bx,ax
  6614 00002A82 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6615                              <1> 	;mov	al,[es:bx]
  6616                              <1> 			; sector number
  6617 00002A84 8A03                <1> 	mov	al,[ebx]
  6618 00002A86 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6619 00002A89 28C0                <1> 	sub	al,al
  6620 00002A8B 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6621 00002A8E E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6622 00002A93 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6623 00002A95 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6624 00002A9A 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6625 00002A9C E8C3020000          <1> 	call	CHECK_STATUS
  6626                              <1> INIT_EXIT:
  6627 00002AA1 C3                  <1> 	RETn
  6628                              <1> 
  6629                              <1> ;----------------------------------------
  6630                              <1> ;	READ LONG	     (AH = 0AH) :
  6631                              <1> ;----------------------------------------
  6632                              <1> 
  6633                              <1> RD_LONG:
  6634                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6635 00002AA2 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6636 00002AA6 E9E0000000          <1>         JMP     COMMANDI
  6637                              <1> 
  6638                              <1> ;----------------------------------------
  6639                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6640                              <1> ;----------------------------------------
  6641                              <1> 
  6642                              <1> WR_LONG:
  6643                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6644 00002AAB C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6645 00002AAF E92C010000          <1>         JMP     COMMANDO
  6646                              <1> 
  6647                              <1> ;----------------------------------------
  6648                              <1> ;	SEEK		     (AH = 0CH) :
  6649                              <1> ;----------------------------------------
  6650                              <1> 
  6651                              <1> DISK_SEEK:
  6652 00002AB4 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6653 00002AB8 E89A010000          <1> 	CALL	COMMAND
  6654 00002ABD 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6655 00002ABF E80C020000          <1> 	CALL	_WAIT
  6656 00002AC4 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6657 00002AC6 E899020000          <1> 	CALL	CHECK_STATUS
  6658 00002ACB 803D[3F6E0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6659 00002AD2 7507                <1> 	JNE	short DS_EXIT
  6660 00002AD4 C605[3F6E0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6661                              <1> DS_EXIT:
  6662 00002ADB C3                  <1> 	RETn
  6663                              <1> 
  6664                              <1> ;----------------------------------------
  6665                              <1> ;	TEST DISK READY      (AH = 10H) :
  6666                              <1> ;----------------------------------------
  6667                              <1> 
  6668                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6669 00002ADC E82B020000          <1> 	CALL	NOT_BUSY
  6670 00002AE1 751C                <1> 	JNZ	short TR_EX
  6671 00002AE3 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6672 00002AE6 668B15[94680000]    <1> 	MOV	DX,[HF_PORT]
  6673 00002AED 80C206              <1> 	add	dl,6
  6674 00002AF0 EE                  <1> 	OUT	DX,AL
  6675 00002AF1 E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6676 00002AF6 7507                <1> 	JNZ	short TR_EX
  6677 00002AF8 C605[3F6E0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6678                              <1> TR_EX:	
  6679 00002AFF C3                  <1> 	RETn
  6680                              <1> 
  6681                              <1> ;----------------------------------------
  6682                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6683                              <1> ;----------------------------------------
  6684                              <1> 
  6685                              <1> HDISK_RECAL:
  6686 00002B00 C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6687 00002B04 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6688 00002B09 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6689 00002B0B E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6690 00002B10 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6691 00002B12 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6692 00002B17 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6693                              <1> RECAL_X:
  6694 00002B19 E846020000          <1> 	CALL	CHECK_STATUS
  6695 00002B1E 803D[3F6E0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6696 00002B25 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6697 00002B27 C605[3F6E0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6698                              <1> RECAL_EXIT:
  6699 00002B2E 803D[3F6E0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6700 00002B35 C3                  <1> 	RETn
  6701                              <1> 
  6702                              <1> ;----------------------------------------
  6703                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6704                              <1> ;----------------------------------------
  6705                              <1> 
  6706                              <1> CTLR_DIAGNOSTIC:
  6707 00002B36 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6708 00002B37 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6709                              <1> 	;AND	AL,0BFH
  6710 00002B39 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6711                              <1> 	;JMP	$+2
  6712                              <1> 	IODELAY
  2133 00002B3B EB00                <2>  jmp short $+2
  2134 00002B3D EB00                <2>  jmp short $+2
  6713 00002B3F E6A1                <1> 	OUT	INTB01,AL
  6714                              <1> 	IODELAY
  2133 00002B41 EB00                <2>  jmp short $+2
  2134 00002B43 EB00                <2>  jmp short $+2
  6715 00002B45 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6716 00002B47 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6717                              <1> 	;JMP	$+2
  6718                              <1> 	IODELAY
  2133 00002B49 EB00                <2>  jmp short $+2
  2134 00002B4B EB00                <2>  jmp short $+2
  6719 00002B4D E621                <1> 	OUT	INTA01,AL
  6720 00002B4F FB                  <1> 	STI
  6721 00002B50 E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6722 00002B55 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6723                              <1> 	;MOV	DX, HF_PORT+7
  6724 00002B57 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  6725 00002B5E 80C207              <1> 	add	dl, 7
  6726 00002B61 B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6727 00002B63 EE                  <1> 	OUT	DX,AL
  6728 00002B64 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6729 00002B69 B480                <1> 	MOV	AH,TIME_OUT
  6730 00002B6B 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6731                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6732 00002B6D 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  6733 00002B74 FEC2                <1> 	inc	dl
  6734 00002B76 EC                  <1> 	IN	AL,DX
  6735 00002B77 A2[366E0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6736 00002B7C B400                <1> 	MOV	AH,0
  6737 00002B7E 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6738 00002B80 7402                <1> 	JE	SHORT CD_EXIT
  6739 00002B82 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6740                              <1> CD_EXIT:
  6741 00002B84 8825[3F6E0000]      <1> 	MOV	[DISK_STATUS1],AH
  6742 00002B8A C3                  <1> 	RETn
  6743                              <1> 
  6744                              <1> ;----------------------------------------
  6745                              <1> ; COMMANDI				:
  6746                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6747                              <1> ;	NSECTOR RETURNS ZERO		:
  6748                              <1> ;----------------------------------------
  6749                              <1> COMMANDI:
  6750 00002B8B E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6751 00002B90 724D                <1> 	JC	short CMD_ABORT
  6752                              <1> 	;MOV	DI,BX
  6753 00002B92 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6754 00002B94 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6755 00002B99 7544                <1> 	JNZ	short CMD_ABORT
  6756                              <1> CMD_I1:
  6757 00002B9B E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6758 00002BA0 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6759                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6760 00002BA2 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6761                              <1> 	;MOV	DX,HF_PORT
  6762 00002BA7 668B15[94680000]    <1> 	mov	dx,[HF_PORT]
  6763 00002BAE FA                  <1> 	CLI
  6764 00002BAF FC                  <1> 	CLD
  6765 00002BB0 F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6766 00002BB3 FB                  <1> 	STI
  6767 00002BB4 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6768 00002BB8 7419                <1> 	JZ	CMD_I3
  6769 00002BBA E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6770 00002BBF 721E                <1> 	JC	short TM_OUT
  6771                              <1> 	;MOV	DX,HF_PORT
  6772 00002BC1 668B15[94680000]    <1> 	mov	dx,[HF_PORT]
  6773                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6774 00002BC8 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6775 00002BCD EC                  <1> CMD_I2: IN	AL,DX
  6776                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6777 00002BCE 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6778 00002BD0 47                  <1> 	INC	eDI
  6779 00002BD1 E2FA                <1> 	LOOP	CMD_I2
  6780 00002BD3 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6781 00002BD8 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6782 00002BDA FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6783 00002BDD 75BC                <1> 	JNZ	SHORT CMD_I1
  6784                              <1> CMD_ABORT:
  6785 00002BDF C3                  <1> TM_OUT: RETn
  6786                              <1> 
  6787                              <1> ;----------------------------------------
  6788                              <1> ; COMMANDO				:
  6789                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6790                              <1> ;	NSECTOR RETURNS ZERO		:
  6791                              <1> ;----------------------------------------
  6792                              <1> COMMANDO:
  6793 00002BE0 E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6794 00002BE5 72F8                <1> 	JC	short CMD_ABORT
  6795 00002BE7 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6796 00002BE9 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6797 00002BEE 75EF                <1> 	JNZ	short CMD_ABORT
  6798 00002BF0 E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6799 00002BF5 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6800                              <1> CMD_O1: ;PUSH	DS
  6801                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6802                              <1> 	;POP	DS
  6803                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6804                              <1> 	;MOV	DX,HF_PORT
  6805                              <1> 	; 01/02/2015
  6806 00002BF7 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  6807                              <1> 	;push	es
  6808                              <1> 	;pop	ds
  6809                              <1> 	;mov	cx, 256
  6810 00002BFE B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6811 00002C03 FA                  <1> 	CLI
  6812 00002C04 FC                  <1> 	CLD
  6813 00002C05 F3666F              <1> 	REP	OUTSW
  6814 00002C08 FB                  <1> 	STI
  6815                              <1> 	;POP	DS			; RESTORE DS
  6816 00002C09 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6817 00002C0D 7419                <1> 	JZ	short CMD_O3
  6818 00002C0F E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6819 00002C14 72C9                <1> 	JC	short TM_OUT
  6820                              <1> 	;MOV	DX,HF_PORT
  6821 00002C16 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  6822                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6823 00002C1D B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6824                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6825 00002C22 8A06                <1> 	mov	al, [esi]
  6826 00002C24 EE                  <1> 	OUT	DX,AL
  6827 00002C25 46                  <1> 	INC	eSI
  6828 00002C26 E2FA                <1> 	LOOP	CMD_O2
  6829                              <1> CMD_O3:
  6830 00002C28 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6831 00002C2D 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6832 00002C2F E830010000          <1> 	CALL	CHECK_STATUS
  6833 00002C34 75A9                <1> 	JNZ	short CMD_ABORT
  6834 00002C36 F605[356E0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6835 00002C3D 75B8                <1> 	JNZ	SHORT CMD_O1
  6836                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6837 00002C3F 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  6838                              <1> 	;add	dl, 2
  6839 00002C46 FEC2                <1> 	inc	dl
  6840 00002C48 FEC2                <1> 	inc	dl
  6841 00002C4A EC                  <1> 	IN	AL,DX			;
  6842 00002C4B A8FF                <1> 	TEST	AL,0FFH 		;
  6843 00002C4D 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6844 00002C4F C605[3F6E0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6845                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6846                              <1> CMD_O4:
  6847 00002C56 C3                  <1> 	RETn
  6848                              <1> 
  6849                              <1> ;--------------------------------------------------------
  6850                              <1> ; COMMAND						:
  6851                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6852                              <1> ; OUTPUT						:
  6853                              <1> ;	BL = STATUS					:
  6854                              <1> ;	BH = ERROR REGISTER				:
  6855                              <1> ;--------------------------------------------------------
  6856                              <1> 
  6857                              <1> COMMAND:
  6858 00002C57 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6859                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6860                              <1> COMMAND1:
  6861                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6862 00002C58 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6863                              <1> 	;;POP	CX
  6864 00002C5D 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6865 00002C5F 803D[3F6E0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6866                              <1> 	;JZ	short CMD_TIMEOUT
  6867                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6868                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6869 00002C66 7507                <1> 	jne	short COMMAND4
  6870                              <1> CMD_TIMEOUT:
  6871 00002C68 C605[3F6E0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6872                              <1> COMMAND4:
  6873 00002C6F 5B                  <1> 	POP	eBX
  6874 00002C70 803D[3F6E0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6875 00002C77 C3                  <1> 	RETn
  6876                              <1> COMMAND2:
  6877 00002C78 5B                  <1> 	POP	eBX
  6878 00002C79 57                  <1> 	PUSH	eDI
  6879 00002C7A C605[376E0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6880 00002C81 FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6881 00002C82 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6882                              <1> 	;AND	AL,0BFH
  6883 00002C84 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6884                              <1> 	;JMP	$+2
  6885                              <1> 	IODELAY
  2133 00002C86 EB00                <2>  jmp short $+2
  2134 00002C88 EB00                <2>  jmp short $+2
  6886 00002C8A E6A1                <1> 	OUT	INTB01,AL
  6887 00002C8C E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6888 00002C8E 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6889                              <1> 	;JMP	$+2
  6890                              <1> 	IODELAY
  2133 00002C90 EB00                <2>  jmp short $+2
  2134 00002C92 EB00                <2>  jmp short $+2
  6891 00002C94 E621                <1> 	OUT	INTA01,AL
  6892 00002C96 FB                  <1> 	STI
  6893 00002C97 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6894                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6895 00002C99 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  6896 00002CA0 FEC2                <1> 	inc	dl
  6897 00002CA2 F605[416E0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6898 00002CA9 7411                <1> 	JZ	short COMMAND3
  6899 00002CAB 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6900 00002CAE 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6901 00002CB0 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6902 00002CB2 7208                <1> 	JB	short COMMAND3
  6903 00002CB4 3C40                <1> 	CMP	AL,40H
  6904 00002CB6 7704                <1> 	JA	short COMMAND3
  6905 00002CB8 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6906                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6907                              <1> COMMAND3:
  6908 00002CBC 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6909 00002CC0 EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6910                              <1> 	IODELAY
  2133 00002CC1 EB00                <2>  jmp short $+2
  2134 00002CC3 EB00                <2>  jmp short $+2
  6911 00002CC5 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6912 00002CC6 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6913 00002CC8 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6914 00002CCC 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6915 00002CCE 5F                  <1> 	POP	eDI
  6916 00002CCF C3                  <1> 	RETn				; ZERO FLAG IS SET
  6917                              <1> 
  6918                              <1> ;CMD_TIMEOUT:
  6919                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6920                              <1> ;COMMAND4:
  6921                              <1> ;	POP	BX
  6922                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6923                              <1> ;	RETn
  6924                              <1> 
  6925                              <1> ;----------------------------------------
  6926                              <1> ;	WAIT FOR INTERRUPT		:
  6927                              <1> ;----------------------------------------
  6928                              <1> ;WAIT:
  6929                              <1> _WAIT:
  6930 00002CD0 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6931                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6932                              <1> 	;CLC
  6933                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6934                              <1> 	;INT	15H
  6935                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6936                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6937                              <1> 
  6938                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6939                              <1> 	;; 21/02/2015
  6940                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6941                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6942 00002CD1 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6943                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6944                              <1> ;-----	WAIT LOOP
  6945                              <1> 
  6946                              <1> WT1:	
  6947                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6948 00002CD6 F605[376E0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6949                              <1> 	;LOOPZ	WT1
  6950 00002CDD 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6951                              <1> 	;DEC	BL
  6952                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6953                              <1> 
  6954                              <1> WT1_hi:
  6955 00002CDF E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6956 00002CE1 A810                <1> 	test	al, 10h			; transition on memory
  6957 00002CE3 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6958                              <1> WT1_lo:
  6959 00002CE5 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6960 00002CE7 A810                <1> 	test	al, 10h			
  6961 00002CE9 74FA                <1> 	jz	short WT1_lo
  6962 00002CEB E2E9                <1> 	loop	WT1
  6963                              <1> 	;;or	bl, bl
  6964                              <1> 	;;jz	short WT2	
  6965                              <1> 	;;dec	bl
  6966                              <1> 	;;jmp	short WT1
  6967                              <1> 	;dec	bl
  6968                              <1> 	;jnz	short WT1	
  6969                              <1> 
  6970 00002CED C605[3F6E0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6971 00002CF4 EB0E                <1> 	JMP	SHORT WT4
  6972 00002CF6 C605[3F6E0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6973 00002CFD C605[376E0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6974 00002D04 803D[3F6E0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6975 00002D0B C3                  <1> 	RETn
  6976                              <1> 
  6977                              <1> ;----------------------------------------
  6978                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6979                              <1> ;----------------------------------------
  6980                              <1> NOT_BUSY:
  6981 00002D0C FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6982                              <1> 	;PUSH	eBX
  6983                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6984 00002D0D 668B15[94680000]    <1> 	mov	DX, [HF_PORT]
  6985 00002D14 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6986                              <1> 	;MOV	BL,DELAY_1
  6987                              <1> 					; wait for 10 seconds
  6988                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6989                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6990                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6991 00002D17 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6992                              <1> 	;
  6993                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6994                              <1> NB1:	
  6995 00002D1C EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6996                              <1> 	;TEST	AL,ST_BUSY
  6997 00002D1D 2480                <1> 	and	al, ST_BUSY
  6998                              <1> 	;LOOPNZ	NB1
  6999 00002D1F 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  7000                              <1> 	;DEC	BL			
  7001                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  7002                              <1> 
  7003 00002D21 E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  7004 00002D23 A810                <1> 	TEST	AL,010H			; transition on memory
  7005 00002D25 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  7006 00002D27 E461                <1> NB1_lo: IN	AL,SYS1
  7007 00002D29 A810                <1> 	TEST	AL,010H
  7008 00002D2B 74FA                <1> 	JZ	short NB1_lo
  7009 00002D2D E2ED                <1> 	LOOP	NB1
  7010                              <1> 	;dec	bl
  7011                              <1> 	;jnz	short NB1
  7012                              <1> 	;
  7013                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  7014                              <1> ;;	jb	short NB1
  7015                              <1> 	;
  7016                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  7017                              <1> 	;JMP	SHORT NB3
  7018 00002D2F B080                <1> 	mov	al, TIME_OUT
  7019                              <1> NB2:	
  7020                              <1> 	;MOV	byte [DISK_STATUS1],0
  7021                              <1> ;NB3:	
  7022                              <1> 	;POP	eBX
  7023 00002D31 A2[3F6E0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  7024                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  7025 00002D36 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  7026 00002D38 C3                  <1> 	RETn
  7027                              <1> 
  7028                              <1> ;----------------------------------------
  7029                              <1> ;	WAIT FOR DATA REQUEST		:
  7030                              <1> ;----------------------------------------
  7031                              <1> WAIT_DRQ:
  7032                              <1> 	;MOV	CX,DELAY_3
  7033                              <1> 	;MOV	DX,HF_PORT+7
  7034 00002D39 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  7035 00002D40 80C207              <1> 	add	dl, 7
  7036                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7037                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7038                              <1> 					; (but it is written as 2000
  7039                              <1> 					; micro seconds in ATORGS.ASM file
  7040                              <1> 					; of Award Bios - 1999, D1A0622)
  7041 00002D43 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7042 00002D48 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7043 00002D49 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7044 00002D4B 7516                <1> 	JNZ	short WQ_OK
  7045                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7046                              <1> WQ_hi:	
  7047 00002D4D E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7048 00002D4F A810                <1> 	TEST	AL,010H			; transition on memory
  7049 00002D51 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7050 00002D53 E461                <1> WQ_lo:  IN      AL,SYS1
  7051 00002D55 A810                <1> 	TEST	AL,010H
  7052 00002D57 74FA                <1> 	JZ	SHORT WQ_lo
  7053 00002D59 E2ED                <1> 	LOOP	WQ_1
  7054                              <1> 
  7055 00002D5B C605[3F6E0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7056 00002D62 F9                  <1> 	STC
  7057                              <1> WQ_OK:
  7058 00002D63 C3                  <1> 	RETn
  7059                              <1> ;WQ_OK:	;CLC
  7060                              <1> ;	RETn
  7061                              <1> 
  7062                              <1> ;----------------------------------------
  7063                              <1> ;	CHECK FIXED DISK STATUS 	:
  7064                              <1> ;----------------------------------------
  7065                              <1> CHECK_STATUS:
  7066 00002D64 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7067 00002D69 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7068 00002D6B A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7069 00002D6D 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7070 00002D6F E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7071                              <1> CHECK_S1:
  7072 00002D74 803D[3F6E0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7073 00002D7B C3                  <1> 	RETn
  7074                              <1> 
  7075                              <1> ;----------------------------------------
  7076                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7077                              <1> ;----------------------------------------
  7078                              <1> CHECK_ST:
  7079                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7080 00002D7C 668B15[94680000]    <1> 	mov	dx, [HF_PORT]
  7081 00002D83 80C207              <1> 	add	dl, 7
  7082 00002D86 EC                  <1> 	IN	AL,DX
  7083 00002D87 A2[356E0000]        <1> 	MOV	[HF_STATUS],AL
  7084 00002D8C B400                <1> 	MOV	AH,0
  7085 00002D8E A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7086 00002D90 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7087 00002D92 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7088 00002D94 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7089 00002D96 7514                <1> 	JNZ	short CKST_EXIT
  7090 00002D98 B4AA                <1> 	MOV	AH,NOT_RDY
  7091 00002D9A A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7092 00002D9C 740E                <1> 	JZ	short CKST_EXIT
  7093 00002D9E B440                <1> 	MOV	AH,BAD_SEEK
  7094 00002DA0 A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7095 00002DA2 7408                <1> 	JZ	short CKST_EXIT
  7096 00002DA4 B411                <1> 	MOV	AH,DATA_CORRECTED
  7097 00002DA6 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7098 00002DA8 7502                <1> 	JNZ	short CKST_EXIT
  7099 00002DAA B400                <1> 	MOV	AH,0
  7100                              <1> CKST_EXIT:
  7101 00002DAC 8825[3F6E0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7102 00002DB2 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7103 00002DB5 7403                <1> 	JZ	short CKST_EX1
  7104 00002DB7 80FC00              <1> 	CMP	AH,0
  7105                              <1> CKST_EX1:
  7106 00002DBA C3                  <1> 	RETn
  7107                              <1> 
  7108                              <1> ;----------------------------------------
  7109                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7110                              <1> ;----------------------------------------
  7111                              <1> CHECK_ER:
  7112                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7113 00002DBB 668B15[94680000]    <1> 	mov	dx, [HF_PORT]		;
  7114 00002DC2 FEC2                <1> 	inc	dl
  7115 00002DC4 EC                  <1> 	IN	AL,DX
  7116 00002DC5 A2[366E0000]        <1> 	MOV	[HF_ERROR],AL
  7117 00002DCA 53                  <1> 	PUSH	eBX ; 21/02/2015
  7118 00002DCB B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7119 00002DD0 D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7120 00002DD2 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7121 00002DD4 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7122 00002DD6 BB[88680000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7123 00002DDB 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7124                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7125                              <1> 	;mov	ah, [bx]
  7126 00002DDD 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7127 00002DDF 8825[3F6E0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7128 00002DE5 5B                  <1> 	POP	eBX
  7129 00002DE6 80FC00              <1> 	CMP	AH,0
  7130 00002DE9 C3                  <1> 	RETn
  7131                              <1> 
  7132                              <1> ;--------------------------------------------------------
  7133                              <1> ; CHECK_DMA						:
  7134                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7135                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7136                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7137                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7138                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7139                              <1> ;  -ERROR OTHERWISE					:
  7140                              <1> ;--------------------------------------------------------
  7141                              <1> CHECK_DMA:
  7142                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7143                              <1> 	; 05/12/2021
  7144 00002DEA 50                  <1> 	push	eax
  7145 00002DEB 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7146 00002DEF F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7147 00002DF3 7404                <1> 	JZ	short CKD1
  7148 00002DF5 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7149 00002DF9 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7150 00002DFC 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7151 00002DFE 7207                <1> 	JB	short CKDERR		; TOO MANY
  7152 00002E00 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7153 00002E02 7203                <1> 	JB	short CKDERR		; ERROR
  7154 00002E04 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7155                              <1> 	;POP	AX
  7156                              <1> 	; 05/12/2021
  7157 00002E05 58                  <1> 	pop	eax
  7158 00002E06 C3                  <1> 	RETn				; NORMAL RETURN
  7159 00002E07 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7160 00002E08 C605[3F6E0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7161                              <1> 	;POP	AX
  7162                              <1> 	; 05/12/2021
  7163 00002E0F 58                  <1> 	pop	eax	
  7164 00002E10 C3                  <1> 	RETn
  7165                              <1> 
  7166                              <1> ;----------------------------------------
  7167                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7168                              <1> ;----------------------------------------
  7169                              <1> 					
  7170                              <1> ; INPUT -> DL = 0 based drive number
  7171                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7172                              <1> 
  7173                              <1> GET_VEC:
  7174                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7175                              <1> 	;MOV	ES,AX
  7176                              <1> 	;TEST	DL,1
  7177                              <1> 	;JZ	short GV_0
  7178                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7179                              <1> ;	JMP	SHORT GV_EXIT
  7180                              <1> ;GV_0:
  7181                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7182                              <1> ;
  7183                              <1> 	;xor	bh, bh
  7184 00002E11 31DB                <1> 	xor	ebx, ebx
  7185 00002E13 88D3                <1> 	mov	bl, dl
  7186                              <1> 	;;02/01/2015
  7187                              <1> 	;;shl	bl, 1			; port address offset
  7188                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7189                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7190 00002E15 C0E302              <1> 	shl	bl, 2	;;
  7191                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7192 00002E18 81C3[446E0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7193                              <1> 	;push	word [bx+2]		; dpt segment
  7194                              <1> 	;pop	es
  7195                              <1> 	;mov	bx, [bx]		; dpt offset
  7196 00002E1E 8B1B                <1> 	mov	ebx, [ebx]		
  7197                              <1> ;GV_EXIT:
  7198 00002E20 C3                  <1> 	RETn
  7199                              <1> 
  7200                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7201                              <1> hdc1_int: ; 21/02/2015
  7202                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7203                              <1> ;								:
  7204                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7205                              <1> ;								:
  7206                              <1> ;----------------------------------------------------------------
  7207                              <1> 
  7208                              <1> ; 22/12/2014
  7209                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7210                              <1> ;	 '11/15/85'
  7211                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7212                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7213                              <1> 
  7214                              <1> ;int_76h:
  7215                              <1> HD_INT:
  7216                              <1> 	;push	ax
  7217                              <1> 	; 05/12/2021
  7218 00002E21 50                  <1> 	push	eax
  7219 00002E22 1E                  <1> 	push	ds
  7220                              <1> 	;CALL	DDS
  7221                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7222 00002E23 66B81000            <1> 	mov	ax, KDATA
  7223 00002E27 8ED8                <1> 	mov 	ds, ax
  7224                              <1> 	;
  7225                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7226                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7227 00002E29 C605[376E0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7228                              <1> 	;
  7229                              <1> 	;push	dx
  7230                              <1> 	; 05/12/2021
  7231 00002E30 52                  <1> 	push	edx
  7232 00002E31 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7233                              <1> 					; Clear Controller
  7234                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7235 00002E35 EC                  <1> 	in	al, dx			;
  7236                              <1> 	;pop	dx
  7237                              <1> 	; 05/12/2021
  7238 00002E36 5A                  <1> 	pop	edx
  7239                              <1> 	NEWIODELAY
  2138 00002E37 E6EB                <2>  out 0EBh,al
  7240                              <1> 	;
  7241 00002E39 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7242 00002E3B E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7243                              <1> 	;JMP	$+2			; WAIT
  7244                              <1> 	NEWIODELAY
  2138 00002E3D E6EB                <2>  out 0EBh,al
  7245 00002E3F E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7246 00002E41 1F                  <1> 	pop	ds
  7247                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7248                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7249                              <1> 	;INT	15H			;  INTERRUPT
  7250                              <1> irq15_iret: ; 25/02/2015
  7251                              <1> 	;pop	ax
  7252                              <1> 	; 05/12/2021
  7253 00002E42 58                  <1> 	pop	eax
  7254 00002E43 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7255                              <1> 
  7256                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7257                              <1> hdc2_int: ; 21/02/2015
  7258                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7259                              <1> ;								:
  7260                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7261                              <1> ;								:
  7262                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7263                              <1> 
  7264                              <1> ;int_77h:
  7265                              <1> HD1_INT:
  7266                              <1> 	;push	ax
  7267                              <1> 	; 05/12/2021
  7268 00002E44 50                  <1> 	push	eax
  7269                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7270                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7271 00002E45 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7272 00002E47 E6A0                <1> 	out	0A0h, al
  7273 00002E49 EB00                <1>         jmp short $+2
  7274 00002E4B EB00                <1> 	jmp short $+2
  7275 00002E4D E4A0                <1> 	in	al, 0A0h
  7276 00002E4F 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7277 00002E51 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7278                              <1> 	;
  7279 00002E53 1E                  <1> 	push	ds
  7280                              <1> 	;CALL	DDS
  7281                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7282 00002E54 66B81000            <1> 	mov	ax, KDATA
  7283 00002E58 8ED8                <1> 	mov 	ds, ax
  7284                              <1> 	;
  7285                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7286                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7287 00002E5A 800D[376E0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7288                              <1> 	;
  7289                              <1> 	;push	dx
  7290                              <1> 	; 05/12/2021
  7291 00002E61 52                  <1> 	push	edx
  7292 00002E62 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7293                              <1> 					; Clear Controller (Award BIOS 1999)
  7294 00002E66 EBCD                <1> 	jmp	short Clear_IRQ1415
  7295                              <1> 
  7296                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7297                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7298                              <1> 
  7299                              <1> ;////////////////////////////////////////////////////////////////////
  7300                              <1> ;; END OF DISK I/O SYTEM ///
  2073                                  %include 'memory.s'  ; 09/03/2015
  2074                              <1> ; Retro UNIX 386 v2 - memory.s - 26/01/2020
  2075                              <1> ; Last Modification: 31/12/2021 (Retro UNIX 386 v1.2)
  2076                              <1> ; ----------------------------------------------------------------------------
  2077                              <1> ;
  2078                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2079                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC
  2080                              <1> ; 18/10/2015 (!not completed!)
  2081                              <1> ;
  2082                              <1> ; Source code for NASM - Netwide Assembler (2.11)
  2083                              <1> 
  2084                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2085                              <1> 
  2086                              <1> ;;04/11/2014 (unix386.s)	
  2087                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2088                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2089                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2090                              <1> ;;
  2091                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2092                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2093                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2094                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2095                              <1> 
  2096                              <1> ; 27/04/2015
  2097                              <1> ; 09/03/2015
  2098                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2099                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2100                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2101                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2102                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2103                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2104                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2105                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2106                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2107                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2108                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2109                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2110                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2111                              <1> SWP_DISK_READ_ERR 	   equ 40
  2112                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2113                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2114                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2115                              <1> SWP_DISK_WRITE_ERR         equ 44
  2116                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2117                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2118                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2119                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2120                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2121                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2122                              <1> 					; (Indicates that the page is not allocated
  2123                              <1> 					; for the process, it is a shared or system
  2124                              <1>                                         ; page, it must not be deallocated!)
  2125                              <1> ; 14/12/2020
  2126                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2127                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2128                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2129                              <1> 				; (Out of memory allocation table)	
  2130                              <1> ;
  2131                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2132                              <1> ;;
  2133                              <1> ;; 10/10/2014
  2134                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2135                              <1> ;;
  2136                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2137                              <1> ;;	(virtual address = physical address)
  2138                              <1> ;; KERNEL PAGE TABLES:
  2139                              <1> ;;	Kernel page directory and all page tables are
  2140                              <1> ;;	on memory as initialized, as equal to physical memory
  2141                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2142                              <1> ;;
  2143                              <1> ;;	what for: User pages may be swapped out, when accessing
  2144                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2145                              <1> ;;	kernel would have to swap it in! But it is also may be
  2146                              <1> ;;	in use by a user process. (In system/kernel mode
  2147                              <1> ;;	kernel can access all memory pages even if they are
  2148                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2149                              <1> ;;	cause conflicts.) 
  2150                              <1> ;;	
  2151                              <1> ;;	As result of these conditions,
  2152                              <1> ;;	all kernel pages must be initialized as equal to 
  2153                              <1> ;;	physical layout for preventing page faults. 
  2154                              <1> ;;	Also, calling "allocate page" procedure after
  2155                              <1> ;;	a page fault can cause another page fault (double fault)
  2156                              <1> ;;	if all kernel page tables would not be initialized.
  2157                              <1> ;;
  2158                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2159                              <1> ;;	memory allocation table. (double word aligned)
  2160                              <1> ;;
  2161                              <1> ;;	[next_page] = first/next free space to be searched
  2162                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2163                              <1> ;;
  2164                              <1> ;;	[last_page] = End of memory (users space), as offset
  2165                              <1> ;;	to memory allocation table. (double word aligned)
  2166                              <1> ;;
  2167                              <1> ;; USER PAGE TABLES:
  2168                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2169                              <1> ;;		'ready only' marked copies of the 
  2170                              <1> ;;		parent process's page table entries (for
  2171                              <1> ;;		same physical memory).
  2172                              <1> ;;		(A page will be copied to a new page after
  2173                              <1> ;;		 if it causes R/W page fault.)
  2174                              <1> ;;
  2175                              <1> ;;	Every user process has own (different)
  2176                              <1> ;;	page directory and page tables.	
  2177                              <1> ;;
  2178                              <1> ;;	Code starts at virtual address 0, always.
  2179                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2180                              <1> ;;	(Programs can be written/developed as simple
  2181                              <1> ;;	 flat memory programs.)
  2182                              <1> ;;
  2183                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2184                              <1> ;;	Memory page will be allocated by kernel only 
  2185                              <1> ;;		(in kernel/system mode only).
  2186                              <1> ;;	* After a
  2187                              <1> ;;	  - 'not present' page fault
  2188                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2189                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2190                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2191                              <1> ;;	  request by running process.
  2192                              <1> ;;	* While creating a process, allocating a new buffer,
  2193                              <1> ;;	  new page tables etc.
  2194                              <1> ;;
  2195                              <1> ;;	At first,
  2196                              <1> ;;	- 'allocate page' procedure will be called;
  2197                              <1> ;,	   if it will return with a valid (>0) physical address
  2198                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2199                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2200                              <1> ;;	- 'allocate page' will be called for allocating page
  2201                              <1> ;;	   directory, page table and running space (data/code).
  2202                              <1> ;;	- every successful 'allocate page' call will decrease
  2203                              <1> ;;	  'free_pages' count (pointer).
  2204                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2205                              <1> ;;	  if 'free_pages' points to a ZERO.
  2206                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2207                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2208                              <1> ;;	  error except errors caused by attribute conflicts.
  2209                              <1> ;;	 (swapper functions)	 
  2210                              <1> ;;					
  2211                              <1> ;;	At second,
  2212                              <1> ;;	- page directory entry will be updated then page table
  2213                              <1> ;;	  entry will be updated.		
  2214                              <1> ;;
  2215                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2216                              <1> ;;	- M.A.T. has a size according to available memory as
  2217                              <1> ;;	  follows:
  2218                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2219                              <1> ;;		  - a bit with value of 0 means allocated page
  2220                              <1> ;;		  - a bit with value of 1 means a free page
  2221                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2222                              <1> ;;	  depending on M.A.T.
  2223                              <1> ;;		(NOTE: Free page count will not be checked
  2224                              <1> ;;		again -on M.A.T.- after initialization. 
  2225                              <1> ;;		Kernel will trust on initial count.)
  2226                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2227                              <1> ;;	  and it will be increased by deallocation procedures.
  2228                              <1> ;;	
  2229                              <1> ;;	- Available memory will be calculated during
  2230                              <1> ;;	  the kernel's initialization stage (in real mode).
  2231                              <1> ;;	  Memory allocation table and kernel page tables 
  2232                              <1> ;;	  will be formatted/sized as result of available
  2233                              <1> ;;	  memory calculation before paging is enabled.
  2234                              <1> ;;
  2235                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2236                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2237                              <1> ;;	- Memory allocation for kernel page directory size 
  2238                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2239                              <1> ;;	  for page tables)
  2240                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2241                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2242                              <1> ;;	- User (available) space will be started 
  2243                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2244                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2245                              <1> ;;	  memory allocation table and kernel's page directory
  2246                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2247                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2248                              <1> ;; 	  for buffers.
  2249                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2250                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2251                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2252                              <1> ;;
  2253                              <1> ;; For 1GB Available Memory:
  2254                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2255                              <1> ;;	- Memory allocation for kernel page directory size 
  2256                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2257                              <1> ;;	  for page tables)
  2258                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2259                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2260                              <1> ;;	- User (available) space will be started 
  2261                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2262                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2263                              <1> ;;	  memory allocation table and kernel's page directory
  2264                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2265                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2266                              <1> ;; 	  for buffers.
  2267                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2268                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2269                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2270                              <1> ;;
  2271                              <1> ;;
  2272                              <1> 
  2273                              <1> ;;************************************************************************************
  2274                              <1> ;; 
  2275                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2276                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2277                              <1> 
  2278                              <1> ;; Main factor: "sys fork" system call 
  2279                              <1> ;;	
  2280                              <1> ;; 		FORK
  2281                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2282                              <1> ;;  writable pages ---->|
  2283                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2284                              <1> ;; 
  2285                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2286                              <1> ;; 
  2287                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2288                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2289                              <1> ;;       -while R/W bit is 0-. 
  2290                              <1> ;; 
  2291                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2292                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2293                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2294                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2295                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2296                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2297                              <1> ;; 
  2298                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2299                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2300                              <1> ;;   Parent's PTE attributes are not changed.
  2301                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2302                              <1> ;;    destroy/mix previous fork result).
  2303                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2304                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2305                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2306                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2307                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2308                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2309                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2310                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2311                              <1> ;; 
  2312                              <1> ;; !? WHAT FOR (duplication after duplication):
  2313                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2314                              <1> ;; program/executable code continues from specified location as child process, 
  2315                              <1> ;; returns back previous code location as parent process, every child after 
  2316                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2317                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2318                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2319                              <1> ;; was copied to child's process segment (all of code and data) according to
  2320                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2321                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2322                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2323                              <1> ;; (complete running image of parent process) to the child process; 
  2324                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2325                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2326                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2327                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2328                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2329                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2330                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2331                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2332                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2333                              <1> ;; for sharing same read only pages between parent and child processes.
  2334                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2335                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2336                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2337                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2338                              <1> ;; -deallocation problem-.
  2339                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2340                              <1> ;; 
  2341                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2342                              <1> ;; # Page fault handler will do those:
  2343                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2344                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2345                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2346                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2347                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2348                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2349                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2350                              <1> ;;     to child process.)	
  2351                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2352                              <1> ;; # Page fault handler will do those:
  2353                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2354                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2355                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2356                              <1> ;;     address or not. 
  2357                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2358                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2359                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2360                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2361                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2362                              <1> ;; 
  2363                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2364                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2365                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2366                              <1> ;;       duplication method details, it is not possible multiple child processes
  2367                              <1> ;;       were using same page with duplicated PTEs.
  2368                              <1> ;; 
  2369                              <1> ;;************************************************************************************   
  2370                              <1> 
  2371                              <1> ;; 08/10/2014
  2372                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2373                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2374                              <1> 
  2375                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2376                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2377                              <1> ;; (25/08/2014, Revision: 5057) file 
  2378                              <1> ;; by KolibriOS Team (2004-2012)
  2379                              <1> 
  2380                              <1> allocate_page:
  2381                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2382                              <1> 	;	 (temporary modifications)
  2383                              <1> 	; 01/07/2015
  2384                              <1> 	; 05/05/2015
  2385                              <1> 	; 30/04/2015
  2386                              <1> 	; 16/10/2014
  2387                              <1> 	; 08/10/2014
  2388                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2389                              <1> 	;
  2390                              <1> 	; INPUT -> none
  2391                              <1> 	;
  2392                              <1> 	; OUTPUT ->
  2393                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2394                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2395                              <1> 	;
  2396                              <1> 	;	CF = 1 and EAX = 0 
  2397                              <1> 	; 		   if there is not a free page to be allocated	
  2398                              <1> 	;
  2399                              <1> 	; Modified Registers -> none (except EAX)
  2400                              <1> 	;
  2401 00002E68 A1[B06D0000]        <1> 	mov	eax, [free_pages]
  2402 00002E6D 21C0                <1> 	and	eax, eax
  2403 00002E6F 7438                <1> 	jz	short out_of_memory
  2404                              <1> 	;
  2405 00002E71 53                  <1> 	push	ebx
  2406 00002E72 51                  <1> 	push	ecx
  2407                              <1> 	;
  2408 00002E73 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2409 00002E78 89D9                <1> 	mov	ecx, ebx
  2410                              <1>  				     ; NOTE: 32 (first_page) is initial
  2411                              <1> 				     ; value of [next_page].
  2412                              <1> 				     ; It points to the first available
  2413                              <1> 				     ; page block for users (ring 3) ...	
  2414                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2415                              <1> 				     ; (at the of the first 4 MB)		
  2416 00002E7A 031D[B46D0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2417                              <1> 				 ; next_free_page >> 5
  2418 00002E80 030D[B86D0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2419                              <1> 				 ; (total_pages - 1) >> 5
  2420                              <1> al_p_scan:
  2421 00002E86 39CB                <1> 	cmp	ebx, ecx
  2422 00002E88 770A                <1> 	ja	short al_p_notfound
  2423                              <1> 	;
  2424                              <1> 	; 01/07/2015
  2425                              <1> 	; AMD64 Architecture Programmers Manual
  2426                              <1> 	; Volume 3:
  2427                              <1> 	; General-Purpose and System Instructions
  2428                              <1> 	;
  2429                              <1> 	; BSF - Bit Scan Forward
  2430                              <1> 	;
  2431                              <1> 	;   Searches the value in a register or a memory location
  2432                              <1> 	;   (second operand) for the least-significant set bit. 
  2433                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2434                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2435                              <1> 	;   register (first operand). If the second operand contains 0, 
  2436                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2437                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2438                              <1> 	;   of the searched value
  2439                              <1> 	;
  2440 00002E8A 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2441                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2442                              <1> 			   ; loads the destination with an index to
  2443                              <1> 			   ; first set bit. (0 -> 31) 
  2444                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2445 00002E8D 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2446                              <1> 			 ;
  2447                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2448                              <1> 			 ;	  with value of 1 means 
  2449                              <1> 			 ;	  the corresponding page is free 
  2450                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2451 00002E8F 83C304              <1> 	add	ebx, 4
  2452                              <1> 			 ; We return back for searching next page block
  2453                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2454                              <1> 			 ;	 we always will find at least 1 free page here.
  2455 00002E92 EBF2                <1>         jmp     short al_p_scan
  2456                              <1> 	;
  2457                              <1> al_p_notfound:
  2458 00002E94 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2459 00002E9A 890D[B46D0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2460                              <1> 				 ; (deallocate_page procedure will change it)
  2461 00002EA0 31C0                <1> 	xor	eax, eax
  2462 00002EA2 A3[B06D0000]        <1> 	mov	[free_pages], eax ; 0
  2463 00002EA7 59                  <1> 	pop	ecx
  2464 00002EA8 5B                  <1> 	pop	ebx
  2465                              <1> 	;
  2466                              <1> ; 17/04/2021
  2467                              <1> ; ('swap_out' procedure call is disabled as temporary)
  2468                              <1> 
  2469                              <1> out_of_memory:
  2470                              <1> ;	call	swap_out
  2471                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2472                              <1> ;	;
  2473                              <1> ;	sub 	eax, eax ; 0
  2474 00002EA9 F9                  <1> 	stc
  2475 00002EAA C3                  <1> 	retn
  2476                              <1> 
  2477                              <1> al_p_found:
  2478 00002EAB 89D9                <1> 	mov	ecx, ebx
  2479 00002EAD 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2480 00002EB3 890D[B46D0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2481                              <1> 				 ; address/offset (to the next)
  2482 00002EB9 FF0D[B06D0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2483                              <1> 	;
  2484 00002EBF 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2485                              <1> 				 ; is copied into the Carry Flag and then cleared
  2486                              <1> 				 ; in the destination.
  2487                              <1> 				 ;
  2488                              <1> 				 ; Reset the bit which is corresponding to the 
  2489                              <1> 				 ; (just) allocated page.
  2490                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2491 00002EC2 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2492 00002EC5 01C8                <1> 	add	eax, ecx	 ; = page number
  2493 00002EC7 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2494                              <1> 	; EAX = physical address of memory page
  2495                              <1> 	;
  2496                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2497                              <1> 	;       according to this EAX value...
  2498 00002ECA 59                  <1> 	pop	ecx
  2499 00002ECB 5B                  <1> 	pop	ebx
  2500                              <1> al_p_ok:
  2501 00002ECC C3                  <1> 	retn
  2502                              <1> 
  2503                              <1> make_page_dir:
  2504                              <1> 	; 18/04/2015
  2505                              <1> 	; 12/04/2015
  2506                              <1> 	; 23/10/2014
  2507                              <1> 	; 16/10/2014
  2508                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2509                              <1> 	;
  2510                              <1> 	; INPUT ->
  2511                              <1> 	;	none
  2512                              <1> 	; OUTPUT ->
  2513                              <1> 	;	(EAX = 0)
  2514                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2515                              <1> 	;	cf = 0 ->
  2516                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2517                              <1> 	;		  process/user.
  2518                              <1> 	;
  2519                              <1> 	; Modified Registers -> EAX
  2520                              <1> 	;
  2521 00002ECD E896FFFFFF          <1> 	call	allocate_page
  2522 00002ED2 7216                <1> 	jc	short mkpd_error
  2523                              <1> 	;
  2524 00002ED4 A3[046F0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2525                              <1> 				  ; (Physical address)
  2526                              <1> clear_page:
  2527                              <1> 	; 18/04/2015
  2528                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2529                              <1> 	;
  2530                              <1> 	; INPUT ->
  2531                              <1> 	;	EAX = physical address of the page
  2532                              <1> 	; OUTPUT ->
  2533                              <1> 	;	all bytes of the page will be cleared
  2534                              <1> 	;
  2535                              <1> 	; Modified Registers -> none
  2536                              <1> 	;
  2537 00002ED9 57                  <1> 	push	edi
  2538 00002EDA 51                  <1> 	push	ecx
  2539 00002EDB 50                  <1> 	push	eax
  2540 00002EDC B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2541 00002EE1 89C7                <1> 	mov	edi, eax
  2542 00002EE3 31C0                <1> 	xor	eax, eax
  2543 00002EE5 F3AB                <1> 	rep	stosd
  2544 00002EE7 58                  <1> 	pop	eax
  2545 00002EE8 59                  <1> 	pop	ecx
  2546 00002EE9 5F                  <1> 	pop	edi
  2547                              <1> mkpd_error:
  2548                              <1> mkpt_error:
  2549 00002EEA C3                  <1> 	retn
  2550                              <1> 
  2551                              <1> make_page_table:
  2552                              <1> 	; 23/06/2015
  2553                              <1> 	; 18/04/2015
  2554                              <1> 	; 12/04/2015
  2555                              <1> 	; 16/10/2014
  2556                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2557                              <1> 	;
  2558                              <1> 	; INPUT ->
  2559                              <1> 	;	EBX = virtual (linear) address
  2560                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2561                              <1> 	;	      (higher 20 bits must be ZERO)
  2562                              <1> 	;	      (bit 0 must be 1)	 
  2563                              <1> 	;	u.pgdir = page directory (physical) address
  2564                              <1> 	; OUTPUT ->
  2565                              <1> 	;	EDX = Page directory entry address
  2566                              <1> 	;	EAX = Page table address
  2567                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2568                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2569                              <1> 	;
  2570                              <1> 	; Modified Registers -> EAX, EDX
  2571                              <1> 	;
  2572 00002EEB E878FFFFFF          <1> 	call	allocate_page
  2573 00002EF0 72F8                <1> 	jc	short mkpt_error
  2574 00002EF2 E811000000          <1> 	call	set_pde	
  2575 00002EF7 EBE0                <1> 	jmp	short clear_page
  2576                              <1> 
  2577                              <1> make_page:
  2578                              <1> 	; 24/07/2015
  2579                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2580                              <1> 	;
  2581                              <1> 	; INPUT ->
  2582                              <1> 	;	EBX = virtual (linear) address
  2583                              <1> 	;	ECX = page attributes (lower 12 bits)
  2584                              <1> 	;	      (higher 20 bits must be ZERO)
  2585                              <1> 	;	      (bit 0 must be 1)	 
  2586                              <1> 	;	u.pgdir = page directory (physical) address
  2587                              <1> 	; OUTPUT ->
  2588                              <1> 	;	EBX = Virtual address
  2589                              <1> 	;	(EDX = PTE value)
  2590                              <1> 	;	EAX = Physical address
  2591                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2592                              <1> 	;
  2593                              <1> 	; Modified Registers -> EAX, EDX
  2594                              <1> 	;
  2595 00002EF9 E86AFFFFFF          <1> 	call	allocate_page
  2596 00002EFE 7207                <1> 	jc	short mkp_err
  2597 00002F00 E821000000          <1> 	call	set_pte	
  2598 00002F05 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2599                              <1> mkp_err:
  2600 00002F07 C3                  <1> 	retn
  2601                              <1> 
  2602                              <1> set_pde:	; Set page directory entry (PDE)
  2603                              <1> 	; 20/07/2015
  2604                              <1> 	; 18/04/2015
  2605                              <1> 	; 12/04/2015
  2606                              <1> 	; 23/10/2014
  2607                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2608                              <1> 	;
  2609                              <1> 	; INPUT ->
  2610                              <1> 	;	EAX = physical address
  2611                              <1> 	;	      (use present value if EAX = 0)
  2612                              <1> 	;	EBX = virtual (linear) address
  2613                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2614                              <1> 	;	      (higher 20 bits must be ZERO)
  2615                              <1> 	;	      (bit 0 must be 1)	 
  2616                              <1> 	;	u.pgdir = page directory (physical) address
  2617                              <1> 	; OUTPUT ->
  2618                              <1> 	;	EDX = PDE address
  2619                              <1> 	;	EAX = page table address (physical)
  2620                              <1> 	;	;(CF=1 -> Invalid page address)
  2621                              <1> 	;
  2622                              <1> 	; Modified Registers -> EDX
  2623                              <1> 	;
  2624 00002F08 89DA                <1> 	mov	edx, ebx
  2625 00002F0A C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2626 00002F0D C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2627 00002F10 0315[046F0000]      <1> 	add	edx, [u.pgdir]
  2628                              <1> 	;
  2629 00002F16 21C0                <1> 	and	eax, eax
  2630 00002F18 7506                <1> 	jnz	short spde_1
  2631                              <1> 	;
  2632 00002F1A 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2633                              <1> 	;test	al, 1
  2634                              <1> 	;jz	short spde_2
  2635 00002F1C 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2636                              <1> spde_1:
  2637                              <1> 	;and	cx, 0FFFh
  2638 00002F20 8902                <1> 	mov	[edx], eax
  2639 00002F22 66090A              <1> 	or	[edx], cx
  2640 00002F25 C3                  <1> 	retn
  2641                              <1> ;spde_2: ; error
  2642                              <1> ;	stc
  2643                              <1> ;	retn
  2644                              <1> 
  2645                              <1> set_pte:	; Set page table entry (PTE)
  2646                              <1> 	; 24/07/2015
  2647                              <1> 	; 20/07/2015
  2648                              <1> 	; 23/06/2015
  2649                              <1> 	; 18/04/2015
  2650                              <1> 	; 12/04/2015
  2651                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2652                              <1> 	;
  2653                              <1> 	; INPUT ->
  2654                              <1> 	;	EAX = physical page address
  2655                              <1> 	;	      (use present value if EAX = 0)
  2656                              <1> 	;	EBX = virtual (linear) address
  2657                              <1> 	;	ECX = page attributes (lower 12 bits)
  2658                              <1> 	;	      (higher 20 bits must be ZERO)
  2659                              <1> 	;	      (bit 0 must be 1)	 
  2660                              <1> 	;	u.pgdir = page directory (physical) address
  2661                              <1> 	; OUTPUT ->
  2662                              <1> 	;	EAX = physical page address
  2663                              <1> 	;	(EDX = PTE value)
  2664                              <1> 	;	EBX = virtual address
  2665                              <1> 	;
  2666                              <1> 	;	CF = 1 -> error
  2667                              <1> 	;
  2668                              <1> 	; Modified Registers -> EAX, EDX
  2669                              <1> 	;
  2670 00002F26 50                  <1> 	push	eax
  2671 00002F27 A1[046F0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2672 00002F2C E837000000          <1> 	call 	get_pde
  2673                              <1> 		; EDX = PDE address
  2674                              <1> 		; EAX = PDE value
  2675 00002F31 5A                  <1> 	pop	edx ; physical page address
  2676 00002F32 722A                <1> 	jc	short spte_err ; PDE not present
  2677                              <1> 	;
  2678 00002F34 53                  <1> 	push	ebx ; 24/07/2015
  2679 00002F35 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2680                              <1> 			    ; EDX = PT address (physical)	
  2681 00002F39 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2682 00002F3C 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2683                              <1> 			 ; clear higher 10 bits (PD bits)
  2684 00002F42 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2685 00002F45 01C3                <1> 	add	ebx, eax
  2686                              <1> 	;
  2687 00002F47 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2688 00002F49 A801                <1> 	test	al, 1
  2689 00002F4B 740C                <1> 	jz	short spte_0
  2690 00002F4D 09D2                <1> 	or	edx, edx
  2691 00002F4F 750F                <1> 	jnz	short spte_1
  2692 00002F51 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2693 00002F55 89C2                <1> 	mov	edx, eax
  2694 00002F57 EB09                <1> 	jmp	short spte_2	
  2695                              <1> spte_0:
  2696                              <1> 	; If this PTE contains a swap (disk) address,
  2697                              <1> 	; it can be updated by using 'swap_in' procedure
  2698                              <1> 	; only!
  2699 00002F59 21C0                <1> 	and	eax, eax
  2700 00002F5B 7403                <1> 	jz	short spte_1
  2701                              <1> 	; 24/07/2015
  2702                              <1> 	; swapped page ! (on disk)
  2703 00002F5D 5B                  <1> 	pop	ebx
  2704                              <1> spte_err:
  2705 00002F5E F9                  <1> 	stc
  2706 00002F5F C3                  <1> 	retn
  2707                              <1> spte_1: 
  2708 00002F60 89D0                <1> 	mov	eax, edx
  2709                              <1> spte_2:
  2710 00002F62 09CA                <1> 	or	edx, ecx
  2711                              <1> 	; 23/06/2015
  2712 00002F64 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2713                              <1> 	; 24/07/2015
  2714 00002F66 5B                  <1> 	pop	ebx
  2715 00002F67 C3                  <1> 	retn
  2716                              <1> 
  2717                              <1> get_pde:	; Get present value of the relevant PDE
  2718                              <1> 	; 20/07/2015
  2719                              <1> 	; 18/04/2015
  2720                              <1> 	; 12/04/2015
  2721                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2722                              <1> 	;
  2723                              <1> 	; INPUT ->
  2724                              <1> 	;	EBX = virtual (linear) address
  2725                              <1> 	;	EAX = page directory (physical) address
  2726                              <1> 	; OUTPUT ->
  2727                              <1> 	;	EDX = Page directory entry address
  2728                              <1> 	;	EAX = Page directory entry value
  2729                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2730                              <1> 	; Modified Registers -> EDX, EAX
  2731                              <1> 	;
  2732 00002F68 89DA                <1> 	mov	edx, ebx
  2733 00002F6A C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2734 00002F6D C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2735 00002F70 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2736 00002F72 8B02                <1> 	mov	eax, [edx]
  2737 00002F74 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2738 00002F76 751F                <1> 	jnz	short gpte_retn
  2739 00002F78 F9                  <1> 	stc
  2740                              <1> gpde_retn:	
  2741 00002F79 C3                  <1> 	retn
  2742                              <1> 
  2743                              <1> get_pte:
  2744                              <1> 		; Get present value of the relevant PTE
  2745                              <1> 	; 29/07/2015
  2746                              <1> 	; 20/07/2015
  2747                              <1> 	; 18/04/2015
  2748                              <1> 	; 12/04/2015
  2749                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2750                              <1> 	;
  2751                              <1> 	; INPUT ->
  2752                              <1> 	;	EBX = virtual (linear) address
  2753                              <1> 	;	EAX = page directory (physical) address
  2754                              <1> 	; OUTPUT ->
  2755                              <1> 	;	EDX = Page table entry address (if CF=0)
  2756                              <1> 	;	      Page directory entry address (if CF=1)
  2757                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2758                              <1> 	;	EAX = Page table entry value (page address)
  2759                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2760                              <1> 	; Modified Registers -> EAX, EDX
  2761                              <1> 	;
  2762 00002F7A E8E9FFFFFF          <1> 	call 	get_pde
  2763 00002F7F 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2764                              <1> 	;jnc	short gpte_1
  2765                              <1> 	;retn
  2766                              <1> ;gpte_1:
  2767 00002F81 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2768 00002F85 89DA                <1> 	mov	edx, ebx
  2769 00002F87 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2770 00002F8A 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2771                              <1> 			 ; clear higher 10 bits (PD bits)
  2772 00002F90 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2773 00002F93 01C2                <1> 	add	edx, eax
  2774 00002F95 8B02                <1> 	mov	eax, [edx]
  2775                              <1> gpte_retn:
  2776 00002F97 C3                  <1> 	retn
  2777                              <1> 
  2778                              <1> deallocate_page_dir:
  2779                              <1> 	; 15/09/2015
  2780                              <1> 	; 05/08/2015
  2781                              <1> 	; 30/04/2015
  2782                              <1> 	; 28/04/2015
  2783                              <1> 	; 17/10/2014
  2784                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2785                              <1> 	;
  2786                              <1> 	; INPUT ->
  2787                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2788                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2789                              <1> 	; OUTPUT ->
  2790                              <1> 	;	All of page tables in the page directory
  2791                              <1> 	;	and page dir's itself will be deallocated
  2792                              <1> 	;	except 'read only' duplicated pages (will be converted
  2793                              <1> 	;	to writable pages).
  2794                              <1> 	;
  2795                              <1> 	; Modified Registers -> EAX
  2796                              <1> 	;
  2797                              <1> 	;
  2798 00002F98 56                  <1> 	push	esi
  2799 00002F99 51                  <1> 	push	ecx
  2800 00002F9A 50                  <1> 	push	eax
  2801 00002F9B 89C6                <1> 	mov	esi, eax 
  2802 00002F9D 31C9                <1> 	xor	ecx, ecx
  2803                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2804                              <1> 	; it must not be deallocated
  2805 00002F9F 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2806                              <1> dapd_0:
  2807 00002FA1 AD                  <1> 	lodsd
  2808 00002FA2 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2809 00002FA4 7409                <1> 	jz	short dapd_1	
  2810 00002FA6 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2811 00002FAA E812000000          <1> 	call	deallocate_page_table			
  2812                              <1> dapd_1:
  2813 00002FAF 41                  <1> 	inc	ecx ; page directory entry index
  2814 00002FB0 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2815 00002FB6 72E9                <1> 	jb	short dapd_0
  2816                              <1> dapd_2:
  2817 00002FB8 58                  <1> 	pop	eax
  2818 00002FB9 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2819 00002FBE 59                  <1> 	pop	ecx
  2820 00002FBF 5E                  <1> 	pop	esi
  2821 00002FC0 C3                  <1> 	retn
  2822                              <1> 
  2823                              <1> deallocate_page_table:
  2824                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2825                              <1> 	;	 (temporary modifications)
  2826                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2827                              <1> 	; 19/09/2015
  2828                              <1> 	; 15/09/2015
  2829                              <1> 	; 05/08/2015
  2830                              <1> 	; 30/04/2015
  2831                              <1> 	; 28/04/2015
  2832                              <1> 	; 24/10/2014
  2833                              <1> 	; 23/10/2014
  2834                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2835                              <1> 	;
  2836                              <1> 	; INPUT ->
  2837                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2838                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2839                              <1> 	;	(ECX = page directory entry index)
  2840                              <1> 	; OUTPUT ->
  2841                              <1> 	;	All of pages in the page table and page table's itself
  2842                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2843                              <1> 	;	(will be converted to writable pages).
  2844                              <1> 	;
  2845                              <1> 	; Modified Registers -> EAX
  2846                              <1> 	;
  2847 00002FC1 56                  <1> 	push	esi
  2848 00002FC2 57                  <1> 	push	edi
  2849 00002FC3 52                  <1> 	push	edx
  2850 00002FC4 50                  <1> 	push	eax ; *
  2851 00002FC5 89C6                <1> 	mov	esi, eax 
  2852 00002FC7 31FF                <1> 	xor	edi, edi ; 0
  2853                              <1> dapt_0:
  2854 00002FC9 AD                  <1> 	lodsd
  2855 00002FCA A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2856 00002FCC 7455                <1> 	jz	short dapt_1
  2857                              <1> 	;
  2858 00002FCE A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2859                              <1> 				  ; (must be 1)
  2860 00002FD0 753F                <1> 	jnz	short dapt_3
  2861                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2862 00002FD2 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2863                              <1> 				   ; as child's page ?
  2864 00002FD6 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2865                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2866                              <1> 	; ECX = page directory entry index (0-1023)
  2867 00002FD8 53                  <1> 	push	ebx
  2868 00002FD9 51                  <1> 	push	ecx
  2869 00002FDA 66C1E102            <1> 	shl	cx, 2 ; *4 
  2870 00002FDE 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2871 00002FE0 8B0B                <1> 	mov	ecx, [ebx]
  2872 00002FE2 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2873 00002FE5 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2874 00002FE7 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2875                              <1> 	; EDI = page table entry index (0-1023)
  2876 00002FEC 89FA                <1> 	mov	edx, edi 
  2877 00002FEE 66C1E202            <1> 	shl	dx, 2 ; *4 
  2878 00002FF2 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2879 00002FF4 8B1A                <1> 	mov	ebx, [edx]
  2880 00002FF6 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2881 00002FF9 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2882 00002FFB 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2883 00002FFF 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2884 00003004 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2885 00003006 7507                <1> 	jne	short dapt_2	; not same page
  2886                              <1> 				; deallocate the child's page
  2887 00003008 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2888 0000300B 59                  <1> 	pop	ecx
  2889 0000300C 5B                  <1> 	pop	ebx
  2890 0000300D EB0D                <1> 	jmp	short dapt_4
  2891                              <1> 
  2892                              <1> ; 17/04/2021
  2893                              <1> ; ('dapt_1' is disabled as temporary)
  2894                              <1> ;
  2895                              <1> ;dapt_1:
  2896                              <1> ;	or	eax, eax	; swapped page ?
  2897                              <1> ;	jz	short dapt_5	; no
  2898                              <1> ;				; yes
  2899                              <1> ;	shr	eax, 1
  2900                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2901                              <1> ;				  ; on the swap disk (or in file)
  2902                              <1> ;	jmp	short dapt_5
  2903                              <1> dapt_2:
  2904 0000300F 59                  <1> 	pop	ecx
  2905 00003010 5B                  <1> 	pop	ebx
  2906                              <1> dapt_3:	
  2907                              <1> 	; 12/07/2016
  2908 00003011 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2909 00003015 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2910                              <1> 	;
  2911                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2912 00003017 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2913                              <1> dapt_4:
  2914 0000301C C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2915                              <1> dapt_1:	; 17/04/2021 (temporary)
  2916                              <1> dapt_5:
  2917 00003023 47                  <1> 	inc	edi ; page table entry index
  2918 00003024 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2919 0000302A 729D                <1> 	jb	short dapt_0
  2920                              <1> 	;
  2921 0000302C 58                  <1> 	pop	eax ; *
  2922 0000302D 5A                  <1> 	pop	edx
  2923 0000302E 5F                  <1> 	pop	edi	
  2924 0000302F 5E                  <1> 	pop	esi
  2925                              <1> 	;
  2926                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2927                              <1> 	;retn
  2928                              <1> 
  2929                              <1> deallocate_page:
  2930                              <1> 	; 15/09/2015
  2931                              <1> 	; 28/04/2015
  2932                              <1> 	; 10/03/2015
  2933                              <1> 	; 17/10/2014
  2934                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2935                              <1> 	;
  2936                              <1> 	; INPUT -> 
  2937                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2938                              <1> 	; OUTPUT ->
  2939                              <1> 	;	[free_pages] is increased
  2940                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2941                              <1> 	;	CF = 1 if the page is already deallocated
  2942                              <1> 	; 	       (or not allocated) before.  
  2943                              <1> 	;
  2944                              <1> 	; Modified Registers -> EAX
  2945                              <1> 	;
  2946 00003030 53                  <1> 	push	ebx
  2947 00003031 52                  <1> 	push	edx
  2948                              <1> 	;
  2949 00003032 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2950                              <1> 				     ; 12 bits right
  2951                              <1> 				     ; to get page number
  2952 00003035 89C2                <1> 	mov	edx, eax
  2953                              <1> 	; 15/09/2015
  2954 00003037 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2955                              <1> 				     ; (1 allocation bit = 1 page)
  2956                              <1> 				     ; (1 allocation bytes = 8 pages)
  2957 0000303A 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2958                              <1> 				     ; (to get 32 bit position)			
  2959                              <1> 	;
  2960 0000303D BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2961 00003042 01D3                <1> 	add	ebx, edx
  2962 00003044 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2963                              <1> 				     ; (allocation bit position)	 
  2964 00003047 3B15[B46D0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2965                              <1> 				     ; than the address in 'next_page' ?
  2966                              <1> 				     ; (next/first free page value)		
  2967 0000304D 7306                <1> 	jnb	short dap_1	     ; no	
  2968 0000304F 8915[B46D0000]      <1> 	mov	[next_page], edx     ; yes
  2969                              <1> dap_1:
  2970 00003055 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2971                              <1> 				     ; set relevant bit to 1.
  2972                              <1> 				     ; set CF to the previous bit value	
  2973                              <1> 	;cmc			     ; complement carry flag	
  2974                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2975                              <1> 				     ; if the page is already deallocated
  2976                              <1> 				     ; before.	
  2977 00003058 FF05[B06D0000]      <1>         inc     dword [free_pages]
  2978                              <1> dap_2:
  2979 0000305E 5A                  <1> 	pop	edx
  2980 0000305F 5B                  <1> 	pop	ebx
  2981 00003060 C3                  <1> 	retn
  2982                              <1> 
  2983                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2984                              <1> ;;                                                              ;;
  2985                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2986                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2987                              <1> ;;                                                              ;;
  2988                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2989                              <1> 
  2990                              <1> ;;$Revision: 5057 $
  2991                              <1> 
  2992                              <1> 
  2993                              <1> ;;align 4
  2994                              <1> ;;proc alloc_page
  2995                              <1> 
  2996                              <1> ;;        pushfd
  2997                              <1> ;;        cli
  2998                              <1> ;;        push    ebx
  2999                              <1> ;;;//-
  3000                              <1> ;;        cmp     [pg_data.pages_free], 1
  3001                              <1> ;;        jle     .out_of_memory
  3002                              <1> ;;;//-
  3003                              <1> ;;
  3004                              <1> ;;        mov     ebx, [page_start]
  3005                              <1> ;;        mov     ecx, [page_end]
  3006                              <1> ;;.l1:
  3007                              <1> ;;        bsf     eax, [ebx];
  3008                              <1> ;;        jnz     .found
  3009                              <1> ;;        add     ebx, 4
  3010                              <1> ;;        cmp     ebx, ecx
  3011                              <1> ;;        jb      .l1
  3012                              <1> ;;        pop     ebx
  3013                              <1> ;;        popfd
  3014                              <1> ;;        xor     eax, eax
  3015                              <1> ;;        ret
  3016                              <1> ;;.found:
  3017                              <1> ;;;//-
  3018                              <1> ;;        dec     [pg_data.pages_free]
  3019                              <1> ;;        jz      .out_of_memory
  3020                              <1> ;;;//-
  3021                              <1> ;;        btr     [ebx], eax
  3022                              <1> ;;        mov     [page_start], ebx
  3023                              <1> ;;        sub     ebx, sys_pgmap
  3024                              <1> ;;        lea     eax, [eax+ebx*8]
  3025                              <1> ;;        shl     eax, 12
  3026                              <1> ;;;//-       dec [pg_data.pages_free]
  3027                              <1> ;;        pop     ebx
  3028                              <1> ;;        popfd
  3029                              <1> ;;        ret
  3030                              <1> ;;;//-
  3031                              <1> ;;.out_of_memory:
  3032                              <1> ;;        mov     [pg_data.pages_free], 1
  3033                              <1> ;;        xor     eax, eax
  3034                              <1> ;;        pop     ebx
  3035                              <1> ;;        popfd
  3036                              <1> ;;        ret
  3037                              <1> ;;;//-
  3038                              <1> ;;endp
  3039                              <1> 
  3040                              <1> duplicate_page_dir:
  3041                              <1> 	; 21/09/2015
  3042                              <1> 	; 31/08/2015
  3043                              <1> 	; 20/07/2015
  3044                              <1> 	; 28/04/2015
  3045                              <1> 	; 27/04/2015
  3046                              <1> 	; 18/04/2015
  3047                              <1> 	; 12/04/2015
  3048                              <1> 	; 18/10/2014
  3049                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3050                              <1> 	;
  3051                              <1> 	; INPUT -> 
  3052                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3053                              <1> 	;		    page directory.
  3054                              <1> 	; OUTPUT ->
  3055                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3056                              <1> 	;	       page directory.
  3057                              <1> 	;	(New page directory with new page table entries.)
  3058                              <1> 	;	(New page tables with read only copies of the parent's
  3059                              <1> 	;	pages.)
  3060                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3061                              <1> 	;
  3062                              <1> 	; Modified Registers -> none (except EAX)
  3063                              <1> 	;
  3064 00003061 E802FEFFFF          <1> 	call	allocate_page
  3065 00003066 723E                <1> 	jc	short dpd_err
  3066                              <1> 	;
  3067 00003068 55                  <1> 	push	ebp ; 20/07/2015
  3068 00003069 56                  <1> 	push	esi
  3069 0000306A 57                  <1> 	push	edi
  3070 0000306B 53                  <1> 	push	ebx
  3071 0000306C 51                  <1> 	push	ecx
  3072 0000306D 8B35[046F0000]      <1> 	mov	esi, [u.pgdir]
  3073 00003073 89C7                <1> 	mov	edi, eax
  3074 00003075 50                  <1> 	push	eax ; save child's page directory address
  3075                              <1> 	; 31/08/2015
  3076                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3077                              <1> 	; (use same system space for all user page tables) 
  3078 00003076 A5                  <1> 	movsd
  3079 00003077 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3080 0000307C B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3081                              <1> dpd_0:	
  3082 00003081 AD                  <1> 	lodsd
  3083                              <1> 	;or	eax, eax
  3084                              <1>         ;jnz     short dpd_1
  3085 00003082 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3086 00003084 7508                <1> 	jnz	short dpd_1
  3087                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3088 00003086 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3089 0000308C EB0F                <1> 	jmp	short dpd_2
  3090                              <1> dpd_1:	
  3091 0000308E 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3092 00003092 89C3                <1> 	mov	ebx, eax
  3093                              <1> 	; EBX = Parent's page table address
  3094 00003094 E81F000000          <1> 	call	duplicate_page_table
  3095 00003099 720C                <1> 	jc	short dpd_p_err
  3096                              <1> 	; EAX = Child's page table address
  3097 0000309B 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3098                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3099                              <1> 			 ; (present, writable, user)
  3100                              <1> dpd_2:
  3101 0000309D AB                  <1> 	stosd
  3102 0000309E E2E1                <1> 	loop	dpd_0
  3103                              <1> 	;
  3104 000030A0 58                  <1> 	pop	eax  ; restore child's page directory address
  3105                              <1> dpd_3:
  3106 000030A1 59                  <1> 	pop	ecx
  3107 000030A2 5B                  <1> 	pop	ebx
  3108 000030A3 5F                  <1> 	pop	edi
  3109 000030A4 5E                  <1> 	pop	esi
  3110 000030A5 5D                  <1> 	pop	ebp ; 20/07/2015
  3111                              <1> dpd_err:
  3112 000030A6 C3                  <1> 	retn
  3113                              <1> dpd_p_err:
  3114                              <1> 	; release the allocated pages missing (recover free space)
  3115 000030A7 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3116 000030A8 8B1D[046F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3117 000030AE E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3118 000030B3 29C0                <1> 	sub	eax, eax ; 0
  3119 000030B5 F9                  <1> 	stc
  3120 000030B6 EBE9                <1> 	jmp	short dpd_3	
  3121                              <1> 
  3122                              <1> duplicate_page_table:
  3123                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3124                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3125                              <1> 	;	 (temporary modifications)
  3126                              <1> 	; 16/04/2021 (Retro UNIX 386 v2)
  3127                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3128                              <1> 	; 21/09/2015
  3129                              <1> 	; 20/07/2015
  3130                              <1> 	; 05/05/2015
  3131                              <1> 	; 28/04/2015
  3132                              <1> 	; 27/04/2015
  3133                              <1> 	; 18/04/2015
  3134                              <1> 	; 18/10/2014
  3135                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3136                              <1> 	;
  3137                              <1> 	; INPUT -> 
  3138                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3139                              <1> 	;       20/02/2017		 
  3140                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3141                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3142                              <1> 	; OUTPUT ->
  3143                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3144                              <1> 	;	      (with 'read only' attribute of page table entries)
  3145                              <1> 	;	20/02/2017
  3146                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3147                              <1> 	;	
  3148                              <1> 	;	CF = 1 -> error 
  3149                              <1> 	;
  3150                              <1> 	; Modified Registers -> EBP (except EAX)
  3151                              <1> 	;
  3152 000030B8 E8ABFDFFFF          <1> 	call	allocate_page
  3153 000030BD 725B                <1> 	jc	short dpt_err
  3154                              <1> 	;
  3155 000030BF 50                  <1> 	push	eax ; *
  3156 000030C0 56                  <1> 	push	esi
  3157 000030C1 57                  <1> 	push	edi
  3158 000030C2 52                  <1> 	push	edx
  3159 000030C3 51                  <1> 	push	ecx
  3160                              <1> 	;
  3161 000030C4 89DE                <1> 	mov	esi, ebx
  3162 000030C6 89C7                <1> 	mov	edi, eax
  3163 000030C8 89C2                <1> 	mov	edx, eax
  3164 000030CA 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3165                              <1> dpt_0:
  3166 000030D0 AD                  <1> 	lodsd
  3167 000030D1 21C0                <1> 	and	eax, eax
  3168 000030D3 7435                <1> 	jz	short dpt_3
  3169 000030D5 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3170                              <1> 	; 17/04/2021 (temporary)
  3171 000030D7 7503                <1> 	jnz	short dpt_1
  3172                              <1> 	;jz	short dpt_p_err
  3173                              <1> 	; 31/12/2021
  3174 000030D9 F9                  <1> 	stc
  3175 000030DA EB39                <1> 	jmp	short dpt_p_err
  3176                              <1> 
  3177                              <1> ; 17/04/2021
  3178                              <1> ; ('reload_page' procedure call is disabled as temporary)
  3179                              <1> ;
  3180                              <1> ;	; 20/07/2015
  3181                              <1> ;	; ebp = virtual (linear) address of the memory page
  3182                              <1> ;	call	reload_page ; 28/04/2015
  3183                              <1> ;	jc	short dpt_p_err
  3184                              <1> dpt_1:
  3185                              <1> 	; 21/09/2015
  3186 000030DC 89C1                <1> 	mov	ecx, eax
  3187 000030DE 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3188 000030E2 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3189 000030E5 751A                <1> 	jnz	short dpt_2
  3190                              <1> 	; Read only (parent) page
  3191                              <1> 	; 	- there is a third process which uses this page -
  3192                              <1> 	; Allocate a new page for the child process
  3193 000030E7 E87CFDFFFF          <1> 	call	allocate_page
  3194 000030EC 7227                <1> 	jc	short dpt_p_err
  3195 000030EE 57                  <1> 	push	edi
  3196 000030EF 56                  <1> 	push	esi
  3197 000030F0 89CE                <1> 	mov	esi, ecx
  3198 000030F2 89C7                <1> 	mov	edi, eax
  3199 000030F4 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3200 000030F9 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3201 000030FB 5E                  <1> 	pop	esi
  3202 000030FC 5F                  <1> 	pop	edi
  3203                              <1> 	;
  3204                              <1> 
  3205                              <1> ; 17/04/2021
  3206                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  3207                              <1> ; 
  3208                              <1> ;	push	ebx
  3209                              <1> ;	push	eax
  3210                              <1> ;	; 20/07/2015
  3211                              <1> ;	mov	ebx, ebp
  3212                              <1> ;	; ebx = virtual (linear) address of the memory page
  3213                              <1> ;	call	add_to_swap_queue
  3214                              <1> ;	pop	eax
  3215                              <1> ;	pop	ebx
  3216                              <1> 
  3217                              <1> 	; 21/09/2015
  3218 000030FD 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3219                              <1> 		; user + writable + present page
  3220 000030FF EB09                <1> 	jmp	short dpt_3
  3221                              <1> dpt_2:
  3222                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3223 00003101 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3224                              <1> 		    ; (read only page!)
  3225 00003103 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3226 00003106 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3227                              <1> dpt_3:
  3228 0000310A AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3229                              <1> 	;
  3230 0000310B 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3231                              <1> 	;
  3232 00003111 39D7                <1> 	cmp	edi, edx
  3233 00003113 72BB                <1> 	jb	short dpt_0
  3234                              <1> dpt_p_err:
  3235 00003115 59                  <1> 	pop	ecx
  3236 00003116 5A                  <1> 	pop	edx
  3237 00003117 5F                  <1> 	pop	edi
  3238 00003118 5E                  <1> 	pop	esi
  3239 00003119 58                  <1> 	pop	eax ; *
  3240                              <1> dpt_err:
  3241 0000311A C3                  <1> 	retn
  3242                              <1> 
  3243                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3244                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3245                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3246                              <1> 	;	 (temporary modifications)
  3247                              <1> 	; 21/09/2015
  3248                              <1> 	; 19/09/2015
  3249                              <1> 	; 17/09/2015
  3250                              <1> 	; 28/08/2015
  3251                              <1> 	; 20/07/2015
  3252                              <1> 	; 28/06/2015
  3253                              <1> 	; 03/05/2015
  3254                              <1> 	; 30/04/2015
  3255                              <1> 	; 18/04/2015
  3256                              <1> 	; 12/04/2015
  3257                              <1> 	; 30/10/2014
  3258                              <1> 	; 11/09/2014
  3259                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3260                              <1> 	;
  3261                              <1> 	; Note: This is not an interrupt/exception handler.
  3262                              <1> 	;	This is a 'page fault remedy' subroutine 
  3263                              <1> 	;	which will be called by standard/uniform
  3264                              <1> 	;	exception handler.
  3265                              <1> 	;
  3266                              <1> 	; INPUT -> 
  3267                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3268                              <1> 	;
  3269                              <1> 	;	cr2 = the virtual (linear) address 
  3270                              <1> 	;	      which has caused to page fault (19/09/2015)
  3271                              <1> 	;
  3272                              <1> 	; OUTPUT ->
  3273                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3274                              <1> 	;	EAX = 0 -> no error
  3275                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3276                              <1> 	;
  3277                              <1> 	; Modified Registers -> none (except EAX)
  3278                              <1> 	;	
  3279                              <1>         ;
  3280                              <1>         ; ERROR CODE:
  3281                              <1> 	;	 31  .....	4   3	2   1	0
  3282                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3283                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3284                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3285                              <1> 	;
  3286                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3287                              <1>     	;		a page-protection violation. When not set,
  3288                              <1> 	;		it was caused by a non-present page.
  3289                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3290                              <1> 	;		a page write. When not set, it was caused
  3291                              <1> 	;		by a page read.
  3292                              <1> 	; U : USER    -	When set, the page fault was caused 
  3293                              <1> 	;		while CPL = 3. 
  3294                              <1> 	;		This does not necessarily mean that
  3295                              <1> 	;		the page fault was a privilege violation.
  3296                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3297                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3298                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3299                              <1> 	;     FETCH	an instruction fetch
  3300                              <1> 	;
  3301                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3302                              <1> 	;  31               22                  12 11                    0
  3303                              <1> 	; +-------------------+-------------------+-----------------------+
  3304                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3305                              <1>        	; +-------------------+-------------------+-----------------------+
  3306                              <1> 	;
  3307                              <1> 
  3308                              <1> 	;; CR3 REGISTER (Control Register 3)
  3309                              <1> 	;  31                                   12             5 4 3 2   0
  3310                              <1> 	; +---------------------------------------+-------------+---+-----+
  3311                              <1>       	; |                                       |  		|P|P|     |
  3312                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3313                              <1>       	; |                                       | 		|D|T|     |
  3314                              <1>    	; +---------------------------------------+-------------+---+-----+
  3315                              <1> 	;
  3316                              <1> 	;	PWT    - WRITE THROUGH
  3317                              <1> 	;	PCD    - CACHE DISABLE		
  3318                              <1> 	;
  3319                              <1> 	;
  3320                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3321                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3322                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3323                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3324                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3325                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3326                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3327                              <1> 	;
  3328                              <1>         ;       P      - PRESENT
  3329                              <1>         ;       R/W    - READ/WRITE
  3330                              <1>         ;       U/S    - USER/SUPERVISOR
  3331                              <1> 	;	PWT    - WRITE THROUGH
  3332                              <1> 	;	PCD    - CACHE DISABLE	
  3333                              <1> 	;	A      - ACCESSED	
  3334                              <1>         ;       D      - DIRTY (IGNORED)
  3335                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3336                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3337                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3338                              <1> 	;
  3339                              <1> 	;
  3340                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3341                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3342                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3343                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3344                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3345                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3346                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3347                              <1> 	;
  3348                              <1>         ;       P      - PRESENT
  3349                              <1>         ;       R/W    - READ/WRITE
  3350                              <1>         ;       U/S    - USER/SUPERVISOR
  3351                              <1> 	;	PWT    - WRITE THROUGH
  3352                              <1> 	;	PCD    - CACHE DISABLE	
  3353                              <1> 	;	A      - ACCESSED	
  3354                              <1>         ;       D      - DIRTY
  3355                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3356                              <1> 	;	G      - GLOBAL	 
  3357                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3358                              <1> 	;
  3359                              <1> 	;
  3360                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3361                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3362                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3363                              <1>       	; |                                       |     | | | | | | |U|R| |
  3364                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3365                              <1>       	; |                                       |     | | | | | | |S|W| |
  3366                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3367                              <1> 	;
  3368                              <1>         ;       P      - PRESENT
  3369                              <1>         ;       R/W    - READ/WRITE
  3370                              <1>         ;       U/S    - USER/SUPERVISOR
  3371                              <1>         ;       D      - DIRTY
  3372                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3373                              <1> 	;
  3374                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3375                              <1> 	;
  3376                              <1> 	;
  3377                              <1> 	;; Invalid Page Table Entry
  3378                              <1> 	; 31                                                           1 0
  3379                              <1>       	; +-------------------------------------------------------------+-+
  3380                              <1>       	; |                                                             | |
  3381                              <1>       	; |                          AVAILABLE                          |0|
  3382                              <1>       	; |                                                             | |
  3383                              <1>       	; +-------------------------------------------------------------+-+
  3384                              <1> 	;
  3385                              <1> 
  3386 0000311B 53                  <1> 	push	ebx
  3387 0000311C 52                  <1> 	push	edx
  3388 0000311D 51                  <1> 	push	ecx
  3389                              <1> 	;
  3390                              <1> 	; 21/09/2015 (debugging)
  3391 0000311E FF05[1C6F0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3392 00003124 FF05[606E0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3393                              <1> 	; 28/06/2015
  3394                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3395 0000312A 8A15[586E0000]      <1> 	mov	dl, [error_code]
  3396                              <1> 	;
  3397 00003130 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3398                              <1> 			; sign
  3399 00003133 7416                <1> 	jz	short pfh_alloc_np
  3400                              <1> 	; 
  3401                              <1> 	; If it is not a 'write on read only page' type page fault
  3402                              <1> 	; major page fault error with minor reason must be returned without 
  3403                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3404                              <1> 	; after return here!
  3405                              <1> 	; Page fault will be remedied, by copying page contents
  3406                              <1> 	; to newly allocated page with write permission;
  3407                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3408                              <1> 	; used for working with minimum possible memory usage. 
  3409                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3410                              <1> 	; process with 'read only' flag. If the child process attempts to
  3411                              <1> 	; write on these read only pages, page fault will be directed here
  3412                              <1> 	; for allocating a new page with same data/content. 
  3413                              <1> 	;
  3414                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3415                              <1> 	; will not force to separate CODE and DATA space 
  3416                              <1> 	; in a process/program... 
  3417                              <1> 	; CODE segment/section may contain DATA!
  3418                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3419                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3420                              <1> 	;	
  3421 00003135 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3422                              <1> 			; sign
  3423 00003138 744F                <1>         jz	short pfh_p_err
  3424                              <1> 	; 31/08/2015
  3425 0000313A F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3426                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3427 0000313D 744A                <1>         jz	short pfh_pv_err
  3428                              <1> 	;
  3429                              <1> 	; make a new page and copy the parent's page content
  3430                              <1> 	; as the child's new page content
  3431                              <1> 	;
  3432 0000313F 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3433                              <1> 			 ; which has caused to page fault
  3434 00003142 E87C000000          <1> 	call 	copy_page
  3435 00003147 7239                <1>         jc	short pfh_im_err ; insufficient memory
  3436                              <1> 	;
  3437 00003149 EB72                <1>         jmp     pfh_cpp_ok
  3438                              <1> 	;
  3439                              <1> pfh_alloc_np:
  3440 0000314B E818FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3441 00003150 7230                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3442                              <1> pfh_chk_cpl:
  3443                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3444                              <1> 		; (Lower 12 bits are ZERO, because 
  3445                              <1> 		;	the address is on a page boundary)
  3446 00003152 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3447 00003155 7505                <1> 	jnz	short pfh_um
  3448                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3449 00003157 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3450                              <1> 			 ; of the current/active page directory
  3451                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3452                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3453 0000315A EB06                <1> 	jmp	short pfh_get_pde
  3454                              <1> 	;
  3455                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3456 0000315C 8B1D[046F0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3457                              <1> 			; Physical address of the USER's page directory
  3458                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3459                              <1> pfh_get_pde:
  3460 00003162 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3461 00003165 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3462                              <1> 			 ; which has been caused to page fault
  3463                              <1> 			 ;
  3464 00003168 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3465 0000316B 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3466                              <1> 	;
  3467 0000316E 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3468 00003170 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3469 00003172 F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3470 00003175 741A                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3471                              <1> 			  	  ; set/validate page directory entry
  3472 00003177 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3473 0000317C 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3474 0000317E 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3475 00003180 EB25                <1> 	jmp	short pfh_get_pte
  3476                              <1> 
  3477                              <1> 	; 31/12/2021 (short jump)
  3478                              <1> pfh_im_err:
  3479 00003182 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3480                              <1> 			; Major (Primary) Error: Page Fault
  3481                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3482 00003187 EB36                <1> 	jmp	short pfh_err_retn
  3483                              <1> 
  3484                              <1> 	; 31/12/2021
  3485                              <1> pfh_p_err: ; 09/03/2015
  3486                              <1> pfh_pv_err:
  3487                              <1> 	; Page fault was caused by a protection-violation
  3488 00003189 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3489                              <1> 			; Major (Primary) Error: Page Fault
  3490                              <1> 			; Minor (Secondary) Error: Protection violation !
  3491 0000318E F9                  <1> 	stc
  3492 0000318F EB2E                <1> 	jmp	short pfh_err_retn
  3493                              <1> 
  3494                              <1> pfh_set_pde:
  3495                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3496                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3497                              <1> 	;
  3498 00003191 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3499 00003193 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3500 00003195 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3501 00003197 89C3                <1> 	mov	ebx, eax
  3502 00003199 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3503 0000319E 72E2                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3504                              <1> pfh_spde_1:
  3505                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3506 000031A0 89C1                <1> 	mov	ecx, eax
  3507 000031A2 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3508                              <1> pfh_get_pte:
  3509 000031A7 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3510                              <1> 			 ; which has been caused to page fault
  3511 000031AA 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3512 000031AC C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3513                              <1> 			 ; higher 20 bits of the page fault address 
  3514 000031AF 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3515 000031B4 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3516 000031B7 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3517                              <1> ; 17/04/2021 temporary
  3518                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3519                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3520                              <1> ; 17/04/2021
  3521                              <1> ; ('swap_in' procedure call has been disabled as temporary)
  3522                              <1> ;
  3523                              <1> ;	and	eax, eax
  3524                              <1> ;	jz	short pfh_gpte_1
  3525                              <1> ;	; 20/07/2015
  3526                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3527                              <1> ;	push	ebp ; 20/07/2015
  3528                              <1> ;	mov	ebp, cr2
  3529                              <1> ;		; ECX = physical address of the page table entry
  3530                              <1> ;		; EBX = Memory page address (physical!)
  3531                              <1> ;		; EAX = Swap disk (offset) address
  3532                              <1> ;		; EBP = virtual address (page fault address)
  3533                              <1> ;	call	swap_in
  3534                              <1> ;	pop	ebp
  3535                              <1> ;	jc      short pfh_err_retn
  3536                              <1> ;	xchg	ecx, ebx
  3537                              <1> ;		; EBX = physical address of the page table entry
  3538                              <1> ;		; ECX = new page
  3539                              <1> pfh_gpte_1:
  3540 000031B9 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3541 000031BB 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3542                              <1> pfh_cpp_ok:
  3543                              <1> ; 17/04/2021
  3544                              <1> ; ('add_to_swap_queue' procedure call has been disabled as temporary)
  3545                              <1> ;
  3546                              <1> ;	; 20/07/2015
  3547                              <1> ;	mov	ebx, cr2
  3548                              <1> ;	call 	add_to_swap_queue
  3549                              <1> 	;
  3550                              <1> 	; The new PTE (which contains the new page) will be added to 
  3551                              <1> 	; the swap queue, here. 
  3552                              <1> 	; (Later, if memory will become insufficient, 
  3553                              <1> 	; one page will be swapped out which is at the head of 
  3554                              <1> 	; the swap queue by using FIFO and access check methods.)
  3555                              <1> 	;
  3556 000031BD 31C0                <1> 	xor	eax, eax  ; 0
  3557                              <1> 	;
  3558                              <1> pfh_err_retn:
  3559 000031BF 59                  <1> 	pop	ecx
  3560 000031C0 5A                  <1> 	pop	edx
  3561 000031C1 5B                  <1> 	pop	ebx
  3562 000031C2 C3                  <1> 	retn 
  3563                              <1> 	
  3564                              <1> copy_page:
  3565                              <1> 	; 16/04/2021
  3566                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3567                              <1> 	; 22/09/2015
  3568                              <1> 	; 21/09/2015
  3569                              <1> 	; 19/09/2015
  3570                              <1> 	; 07/09/2015
  3571                              <1> 	; 31/08/2015
  3572                              <1> 	; 20/07/2015
  3573                              <1> 	; 05/05/2015
  3574                              <1> 	; 03/05/2015
  3575                              <1> 	; 18/04/2015
  3576                              <1> 	; 12/04/2015
  3577                              <1> 	; 30/10/2014
  3578                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3579                              <1> 	;
  3580                              <1> 	; INPUT -> 
  3581                              <1> 	;	EBX = Virtual (linear) address of source page
  3582                              <1> 	;	     (Page fault address)
  3583                              <1> 	; OUTPUT ->
  3584                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3585                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3586                              <1> 	;	EAX = 0 (CF = 1) 
  3587                              <1> 	;		if there is not a free page to be allocated
  3588                              <1> 	;	(page content of the source page will be copied
  3589                              <1> 	;	onto the target/new page) 	
  3590                              <1> 	;
  3591                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3592                              <1> 	;
  3593                              <1> 
  3594                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3595                              <1> 	; INPUT: 
  3596                              <1> 	;	EBX = Virtual (linear) address of source page
  3597                              <1> 	;	     (Page fault address)
  3598                              <1> 	; OUTPUT:
  3599                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3600                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3601                              <1> 	;	EAX = 0 (CF = 1) 
  3602                              <1> 	;		if there is not a free page to be allocated
  3603                              <1> 	;	(page content of the source page will be copied
  3604                              <1> 	;	onto the target/new page) 	
  3605                              <1> 	;
  3606                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3607                              <1> 	
  3608 000031C3 56                  <1> 	push	esi ; *
  3609 000031C4 57                  <1> 	push	edi ; **
  3610                              <1> 	; 16/04/2021
  3611                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3612                              <1> 	;push	ebx ; ***
  3613                              <1> 	;push	ecx ; ****
  3614 000031C5 31F6                <1> 	xor 	esi, esi
  3615 000031C7 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3616 000031CA 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3617 000031CC C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3618 000031CF 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3619 000031D2 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3620 000031D4 031D[046F0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3621 000031DA 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3622 000031DC 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3623 000031E0 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3624 000031E2 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3625 000031E8 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3626 000031EC 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3627                              <1> 	; 07/09/2015
  3628 000031EE 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3629                              <1> 				     ; read only page as a child process?)	
  3630 000031F3 7509                <1> 	jnz	short cpp_0 ; yes
  3631 000031F5 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3632 000031F7 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3633 000031FC EB32                <1> 	jmp	short cpp_1
  3634                              <1> cpp_0:
  3635 000031FE 89FE                <1> 	mov	esi, edi
  3636 00003200 0335[086F0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3637 00003206 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3638 00003208 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3639 0000320C 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3640 0000320E 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3641 00003214 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3642 00003218 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3643 0000321A 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3644                              <1> 	; 21/09/2015
  3645 0000321C 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3646 0000321E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3647                              <1> 	;
  3648 00003222 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3649 00003225 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3650                              <1> 	;
  3651 00003227 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3652 0000322C 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3653 0000322E 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3654                              <1> 			    ; Convert child's page to writable page
  3655                              <1> cpp_1:
  3656 00003230 E833FCFFFF          <1> 	call	allocate_page
  3657 00003235 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3658 00003237 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3659 00003239 7405                <1> 	jz	short cpp_2
  3660                              <1> 		; Convert read only page to writable page 
  3661                              <1> 		;(for the parent of the current process)
  3662                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3663                              <1> 	; 22/09/2015
  3664 0000323B 890E                <1> 	mov	[esi], ecx
  3665 0000323D 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3666                              <1> 				 ; 1+2+4 = 7
  3667                              <1> cpp_2:
  3668 00003240 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3669                              <1> 	; 07/09/2015
  3670 00003242 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3671 00003244 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3672 00003249 F3A5                <1> 	rep	movsd ; 31/08/2015
  3673                              <1> cpp_3:		
  3674 0000324B 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3675 0000324D 8903                <1> 	mov	[ebx], eax ; Update PTE
  3676 0000324F 28C0                <1> 	sub	al, al ; clear attributes
  3677                              <1> cpp_4:
  3678                              <1> 	; 16/04/2021
  3679                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3680                              <1> 	;pop	ecx ; ****
  3681                              <1> 	;pop	ebx ; ***
  3682 00003251 5F                  <1> 	pop	edi ; **
  3683 00003252 5E                  <1> 	pop	esi ; *
  3684 00003253 C3                  <1> 	retn
  3685                              <1> 
  3686                              <1> ;; 28/04/2015
  3687                              <1> ;; 24/10/2014
  3688                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3689                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3690                              <1> ;;
  3691                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3692                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3693                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3694                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3695                              <1> ;;
  3696                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3697                              <1> ;;
  3698                              <1> ;; Method:
  3699                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3700                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3701                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3702                              <1> ;;	When a new page is being allocated, swap queue is updated
  3703                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3704                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3705                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3706                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3707                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3708                              <1> ;;	offset value becomes it's previous offset value - 4.
  3709                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3710                              <1> ;;	the queue/list is not shifted.
  3711                              <1> ;;	After the queue/list shift, newly allocated page is added
  3712                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3713                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3714                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3715                              <1> ;;	
  3716                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3717                              <1> ;;	the first non-accessed, writable page in the list, 
  3718                              <1> ;;	from the head to the tail. The list is shifted to left 
  3719                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3720                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3721                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3722                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3723                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3724                              <1> ;;	procedure will be failed)...
  3725                              <1> ;;
  3726                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3727                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3728                              <1> ;;	(PTE) will be added to the tail of the queue after
  3729                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3730                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3731                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3732                              <1> ;;
  3733                              <1> ;;
  3734                              <1> ;;	
  3735                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3736                              <1> ;;
  3737                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3738                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3739                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3740                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3741                              <1> ;;
  3742                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3743                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3744                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3745                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3746                              <1> ;; 		 (entire swap space must be accessed by using
  3747                              <1> ;;		 31 bit offset address) 
  3748                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3749                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3750                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3751                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3752                              <1> ;;
  3753                              <1> ;; 					
  3754                              <1> ;; Method:
  3755                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3756                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3757                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3758                              <1> ;;	Swapping out is performed by using swap page queue.
  3759                              <1> ;;
  3760                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3761                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3762                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3763                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3764                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3765                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3766                              <1> ;;	calculated by adding offset value to the swap partition's 
  3767                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3768                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3769                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3770                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3771                              <1> ;;	is in a partitioned virtual hard disk.) 
  3772                              <1> ;;
  3773                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3774                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3775                              <1> ;;
  3776                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3777                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3778                              <1> ;;
  3779                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3780                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3781                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3782                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3783                              <1> ;;	it means relevant (respective) block is in use, and, 
  3784                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3785                              <1> ;;      swap disk/file block is free.
  3786                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3787                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3788                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3789                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3790                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3791                              <1> ;;	------------------------------------------------------------
  3792                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3793                              <1> ;;	------------------------------------------------------------
  3794                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3795                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3796                              <1> ;;
  3797                              <1> ;;	..............................................................
  3798                              <1> ;;
  3799                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3800                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3801                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3802                              <1> ;;	position with value of 1 on the table is converted to swap
  3803                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3804                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3805                              <1> ;;	number of physical swap disk or virtual swap disk)
  3806                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3807                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3808                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3809                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3810                              <1> ;;	If disk write procedure returns with error or free count of 
  3811                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3812                              <1> ;;	'insufficient memory error' (cf=1). 
  3813                              <1> ;;
  3814                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3815                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3816                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3817                              <1> ;;	free blocks after a disk write error. It will return to 
  3818                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3819                              <1> ;;
  3820                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3821                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3822                              <1> ;;	address (cf=0). 
  3823                              <1> ;;
  3824                              <1> ;;	..............................................................
  3825                              <1> ;;
  3826                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3827                              <1> ;;	file sectors at specified memory page. Then page allocation
  3828                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3829                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3830                              <1> ;;	to do, except to terminate the process which is the owner of
  3831                              <1> ;;	the swapped page.
  3832                              <1> ;;
  3833                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3834                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3835                              <1> ;;	updates [swpd_first] pointer if it is required.
  3836                              <1> ;;
  3837                              <1> ;;	..............................................................	 
  3838                              <1> ;;
  3839                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3840                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3841                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3842                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3843                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3844                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3845                              <1> ;;
  3846                              <1> 
  3847                              <1> ; 17/04/2021
  3848                              <1> ; ('swap_in' procedure call is disabled as temporary)
  3849                              <1> 
  3850                              <1> ; 30/11/2021 - temporary !
  3851                              <1> ;swap_in:
  3852                              <1> 	; 31/08/2015
  3853                              <1> 	; 20/07/2015
  3854                              <1> 	; 28/04/2015
  3855                              <1> 	; 18/04/2015
  3856                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3857                              <1> 	;
  3858                              <1> 	; INPUT -> 
  3859                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3860                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3861                              <1> 	;	EAX = Offset Address for the swapped page on the
  3862                              <1> 	;	      swap disk or in the swap file.
  3863                              <1> 	;
  3864                              <1> 	; OUTPUT ->
  3865                              <1> 	;	EAX = 0 if loading at memory has been successful
  3866                              <1> 	;
  3867                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3868                              <1> 	;		  or sector not present or drive not ready
  3869                              <1> 	;	     EAX = Error code
  3870                              <1> 	;	     [u.error] = EAX 
  3871                              <1> 	;		       = The last error code for the process
  3872                              <1> 	;		         (will be reset after returning to user)	  
  3873                              <1> 	;
  3874                              <1> 	; Modified Registers -> EAX
  3875                              <1> 	;
  3876                              <1> 
  3877                              <1> ;       cmp     dword [swp_drv], 0
  3878                              <1> ;	jna	short swpin_dnp_err
  3879                              <1> ;
  3880                              <1> ;	cmp	eax, [swpd_size]
  3881                              <1> ;	jnb	short swpin_snp_err
  3882                              <1> ;
  3883                              <1> ;	push	esi
  3884                              <1> ;	push	ebx
  3885                              <1> ;	push	ecx
  3886                              <1> ;	mov	esi, [swp_drv]	
  3887                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3888                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3889                              <1> ;		; size different than 512 bytes, logical disk sector
  3890                              <1> ;		; size is 512 bytes and disk reading procedure
  3891                              <1> ;		; will be performed for reading 4096 bytes
  3892                              <1> ;		; (2*2048, 8*512). 
  3893                              <1> ;	; ESI = Logical disk description table address
  3894                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3895                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3896                              <1> ;	; ECX = Sector count ; 8 sectors
  3897                              <1> ;	push	eax
  3898                              <1> ;	call	logical_disk_read
  3899                              <1> ;	pop	eax
  3900                              <1> ;	jnc	short swpin_read_ok
  3901                              <1> ;	;
  3902                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3903                              <1> ;	mov	[u.error], eax
  3904                              <1> ;	jmp	short swpin_retn
  3905                              <1> ;	;
  3906                              <1> ;swpin_read_ok:
  3907                              <1> ;	; EAX = Offset address (logical sector number)
  3908                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3909                              <1> ;	;
  3910                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3911                              <1> ;	; 20/07/2015
  3912                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3913                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3914                              <1> ;	mov	bl, [u.uno] ; current process number
  3915                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3916                              <1> ;	call	swap_queue_shift
  3917                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3918                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3919                              <1> ;	; zf = 1
  3920                              <1> ;swpin_retn:
  3921                              <1> ;	pop	ecx
  3922                              <1> ;	pop	ebx
  3923                              <1> ;	pop	esi
  3924                              <1> ;	retn
  3925                              <1> ;
  3926                              <1> ;swpin_dnp_err:
  3927                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3928                              <1> ;swpin_err_retn:
  3929                              <1> ;	mov	[u.error], eax
  3930                              <1> ;	stc
  3931                              <1> ;	retn
  3932                              <1> ;
  3933                              <1> ;swpin_snp_err:
  3934                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3935                              <1> ;	jmp	short swpin_err_retn
  3936                              <1> 
  3937                              <1> ; 17/04/2021
  3938                              <1> ; ('swap_out' procedure call is disabled as temporary)
  3939                              <1> 
  3940                              <1> ; 30/11/2021 - temporary !
  3941                              <1> ;swap_out:
  3942                              <1> 	; 10/06/2016
  3943                              <1> 	; 07/06/2016
  3944                              <1>         ; 23/05/2016
  3945                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3946                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3947                              <1> 	;
  3948                              <1> 	; INPUT -> 
  3949                              <1> 	;	none
  3950                              <1> 	;
  3951                              <1> 	; OUTPUT ->
  3952                              <1> 	;	EAX = Physical page address (which is swapped out
  3953                              <1> 	;	      for allocating a new page)
  3954                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3955                              <1> 	;		  or sector not present or drive not ready
  3956                              <1> 	;	     EAX = Error code
  3957                              <1> 	;	     [u.error] = EAX 
  3958                              <1> 	;		       = The last error code for the process
  3959                              <1> 	;		         (will be reset after returning to user)	  
  3960                              <1> 	;
  3961                              <1> 	; Modified Registers -> none (except EAX)
  3962                              <1> 	;
  3963                              <1> 
  3964                              <1> ;	cmp 	word [swpq_count], 1
  3965                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3966                              <1> ;
  3967                              <1> ;       ;cmp    dword [swp_drv], 1
  3968                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3969                              <1> ;
  3970                              <1> ;       cmp     dword [swpd_free], 1
  3971                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3972                              <1> ;
  3973                              <1> ;	push	ebx ; *
  3974                              <1> ;swpout_1:
  3975                              <1> ;	; 10/06/2016
  3976                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3977                              <1> ;	call	swap_queue_shift
  3978                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3979                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3980                              <1> ;				       ; pointer in the swap queue
  3981                              <1> ;	; EAX = PTE value of the page
  3982                              <1> ;	; EBX = PTE address of the page
  3983                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3984                              <1> ;	;
  3985                              <1> ;	; 07/06/2016
  3986                              <1> ;	; 19/05/2016
  3987                              <1> ;	; check this page is in timer events or not
  3988                              <1> ;	
  3989                              <1> ;swpout_timer_page_0:
  3990                              <1> ;	push	edx ; **
  3991                              <1> ;
  3992                              <1> ;	; 07/06/2016
  3993                              <1> ;	cmp	byte [timer_events], 0 
  3994                              <1> ;	jna	short swpout_2
  3995                              <1> ;	;
  3996                              <1> ;	mov	dl, [timer_events]
  3997                              <1> ;
  3998                              <1> ;	push	ecx ; ***
  3999                              <1> ;	push	ebx ; ****
  4000                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4001                              <1> ;			       ; structures 
  4002                              <1> ;swpout_timer_page_1:
  4003                              <1> ;	mov	cl, [ebx]
  4004                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4005                              <1> ;	jz	short swpout_timer_page_3
  4006                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4007                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4008                              <1> ;				; of the response byte address, to
  4009                              <1> ;				; get beginning of the page address)
  4010                              <1> ;	cmp	eax, ecx
  4011                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4012                              <1> ;	
  4013                              <1> ;	; !same page!
  4014                              <1> ;	;
  4015                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4016                              <1> ;	; This page will be used by the kernel to put timer event
  4017                              <1> ;	; response (signal return) byte at the requested address;
  4018                              <1> ;	; in order to prevent a possible wrong write (while
  4019                              <1> ;	; this page is swapped out) on physical memory,
  4020                              <1> ;	; we must protect this page against to be swapped out!
  4021                              <1> ;	;
  4022                              <1> ;	pop	ebx ; ****
  4023                              <1> ;	pop	ecx ; ***
  4024                              <1> ;	pop	edx ; **
  4025                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4026                              <1> ; 
  4027                              <1> ;swpout_timer_page_2:
  4028                              <1> ;	; 07/06/2016
  4029                              <1> ;	dec	dl
  4030                              <1> ;	jz	short swpout_timer_page_4
  4031                              <1> ;swpout_timer_page_3:
  4032                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4033                              <1> ;	;jnb	short swpout_timer_page_4
  4034                              <1> ;	add	ebx, 16
  4035                              <1> ;	jmp	short swpout_timer_page_1	
  4036                              <1> ;
  4037                              <1> ;swpout_timer_page_4:
  4038                              <1> ;	pop	ebx ; ****
  4039                              <1> ;	pop	ecx ; ***
  4040                              <1> ;swpout_2:
  4041                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4042                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4043                              <1> ;	;
  4044                              <1> ;	call	link_swap_block
  4045                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4046                              <1> ;				       ; because [swpd_free] value
  4047                              <1> ;				       ; was checked at the beginging. 	
  4048                              <1> ;	pop	edx ; **
  4049                              <1> ;	pop	ebx ; *
  4050                              <1> ;	jmp	short swpout_nfspc_err 
  4051                              <1> ;swpout_3:
  4052                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4053                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4054                              <1> ;	;	
  4055                              <1> ;	push	esi ; **
  4056                              <1> ;	push	ecx ; ***
  4057                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4058                              <1> ;	mov	esi, [swp_drv]	
  4059                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4060                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4061                              <1> ;		; size different than 512 bytes, logical disk sector
  4062                              <1> ;		; size is 512 bytes and disk writing procedure
  4063                              <1> ;		; will be performed for writing 4096 bytes
  4064                              <1> ;		; (2*2048, 8*512). 
  4065                              <1> ;	; ESI = Logical disk description table address
  4066                              <1> ;	; EBX = Buffer (Page) address
  4067                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4068                              <1> ;	; ECX = Sector count ; 8 sectors
  4069                              <1> ;	; edx = PTE address
  4070                              <1> ;	call	logical_disk_write
  4071                              <1> ;	; edx = PTE address
  4072                              <1> ;	pop	ecx ; sector address	
  4073                              <1> ;	jnc	short swpout_write_ok
  4074                              <1> ;	;
  4075                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4076                              <1> ;swpout_dw_err:
  4077                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4078                              <1> ;	mov	[u.error], eax
  4079                              <1> ;	jmp	short swpout_retn
  4080                              <1> ;	;
  4081                              <1> ;swpout_write_ok:
  4082                              <1> ;	; EBX = Buffer (page) address
  4083                              <1> ;	; EDX = Page Table Entry address
  4084                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4085                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4086                              <1> ;	mov 	[edx], ecx 
  4087                              <1> ;		; bit 0 = 0 (swapped page)
  4088                              <1> ;	mov	eax, ebx
  4089                              <1> ;swpout_retn:
  4090                              <1> ;	pop	ecx ; ***
  4091                              <1> ;	pop	esi ; **
  4092                              <1> ;	pop	ebx ; *
  4093                              <1> ;	retn
  4094                              <1> ;
  4095                              <1> ;;swpout_dnp_err:
  4096                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4097                              <1> ;;	jmp	short swpout_err_retn
  4098                              <1> ;swpout_nfspc_err:
  4099                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4100                              <1> ;swpout_err_retn:
  4101                              <1> ;	mov	[u.error], eax
  4102                              <1> ;	;stc
  4103                              <1> ;	retn
  4104                              <1> ;swpout_npts_err:
  4105                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4106                              <1> ;	pop	ebx
  4107                              <1> ;	jmp	short swpout_err_retn
  4108                              <1> ;swpout_im_err:
  4109                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4110                              <1> ;	jmp	short swpout_err_retn
  4111                              <1> 
  4112                              <1> ; 17/04/2021
  4113                              <1> ; ('swap_queue_shift' procedure call is disabled as temporary)
  4114                              <1> 
  4115                              <1> ; 30/11/2021 - temporary !
  4116                              <1> ;swap_queue_shift:
  4117                              <1> 	; 26/03/2017
  4118                              <1> 	; 10/06/2016
  4119                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4120                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4121                              <1> 	;
  4122                              <1> 	; INPUT ->
  4123                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4124                              <1> 	;	      and process number combination (bit 0 to 11)
  4125                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4126                              <1> 	;	
  4127                              <1> 	; OUTPUT ->
  4128                              <1> 	;	If EBX input > 0 
  4129                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4130                              <1> 	; 	   from the tail to the head, up to entry offset
  4131                              <1> 	; 	   which points to EBX input value or nothing
  4132                              <1> 	;	   to do if EBX value is not found on the queue.
  4133                              <1> 	;	   (The entry -with EBX value- will be removed
  4134                              <1> 	;	   from the queue if it is found.)
  4135                              <1> 	;
  4136                              <1> 	;	   EAX = 0		
  4137                              <1> 	;
  4138                              <1> 	;	If EBX input = 0
  4139                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4140                              <1> 	; 	   from the tail to the head, if the PTE address
  4141                              <1> 	;	   which is pointed in head of the queue is marked
  4142                              <1> 	;	   as "accessed" or it is marked as "non present".
  4143                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4144                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4145                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4146                              <1> 	;	   -without dropping pointer of the PTE from 
  4147                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4148                              <1> 	;	   Pointer in the head will be moved into the tail,
  4149                              <1> 	;	   other PTEs will be shifted on head direction.)
  4150                              <1> 	;
  4151                              <1> 	;	   Swap queue will be shifted up to the first
  4152                              <1> 	;	   'present' or 'non accessed' page will be found
  4153                              <1> 	;	   (as pointed) on the queue head (then it will be
  4154                              <1>         ;          removed/dropped from the queue).
  4155                              <1> 	;
  4156                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4157                              <1> 	;		 (it's pointer -virtual address-) dropped
  4158                              <1> 	;		 (removed) from swap queue.
  4159                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4160                              <1> 	;	         which is (it's pointer -virtual address-)
  4161                              <1> 	;		 dropped (removed) from swap queue.
  4162                              <1> 	;
  4163                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4164                              <1> 	;
  4165                              <1> 	; Modified Registers -> EAX, EBX
  4166                              <1> 	;
  4167                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4168                              <1> ;	and	ax, ax
  4169                              <1> ;	jz	short swpqs_retn
  4170                              <1> ;	push	edi
  4171                              <1> ;	push	esi
  4172                              <1> ;	push	ecx
  4173                              <1> ;	mov	esi, swap_queue
  4174                              <1> ;	mov	ecx, eax
  4175                              <1> ;	or	ebx, ebx
  4176                              <1> ;	jz	short swpqs_7
  4177                              <1> ;swpqs_1:
  4178                              <1> ;	lodsd
  4179                              <1> ;	cmp	eax, ebx
  4180                              <1> ;	je	short swpqs_2
  4181                              <1> ;	loop	swpqs_1
  4182                              <1> ;	; 10/06/2016
  4183                              <1> ;	sub	eax, eax 
  4184                              <1> ;	jmp	short swpqs_6
  4185                              <1> ;swpqs_2:
  4186                              <1> ;	mov	edi, esi
  4187                              <1> ;	sub 	edi, 4
  4188                              <1> ;swpqs_3:
  4189                              <1> ;	dec	word [swpq_count]
  4190                              <1> ;	jz	short swpqs_5
  4191                              <1> ;swpqs_4:
  4192                              <1> ;	dec 	ecx
  4193                              <1> ;	rep	movsd	; shift up (to the head)
  4194                              <1> ;swpqs_5:
  4195                              <1> ;	xor	eax, eax
  4196                              <1> ;	mov	[edi], eax
  4197                              <1> ;swpqs_6:
  4198                              <1> ;	pop	ecx
  4199                              <1> ;	pop	esi
  4200                              <1> ;	pop	edi
  4201                              <1> ;swpqs_retn:
  4202                              <1> ;	retn		
  4203                              <1> ;swpqs_7:
  4204                              <1> ;	mov	edi, esi ; head
  4205                              <1> ;	lodsd
  4206                              <1> ;	; 20/07/2015
  4207                              <1> ;	mov	ebx, eax
  4208                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4209                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4210                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4211                              <1> ;		      ; ax = process number (1 to 4095)
  4212                              <1> ;	cmp	al, [u.uno]
  4213                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4214                              <1> ;	jne	short swpqs_8
  4215                              <1> ;	mov	eax, [u.pgdir]
  4216                              <1> ;	jmp	short swpqs_9
  4217                              <1> ;swpqs_8:
  4218                              <1> ;	; 09/06/2016
  4219                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4220                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4221                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4222                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4223                              <1> ;
  4224                              <1> ;	;shl	ax, 2
  4225                              <1> ;	shl	al, 2
  4226                              <1> ;	mov 	eax, [eax+p.upage-4]
  4227                              <1> ;	or	eax, eax
  4228                              <1> ;	jz	short swpqs_3 ; invalid upage
  4229                              <1> ;	add	eax, u.pgdir - user
  4230                              <1> ;			 ; u.pgdir value for the process
  4231                              <1> ;			 ; is in [eax]
  4232                              <1> ;	mov	eax, [eax]
  4233                              <1> ;	and	eax, eax
  4234                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4235                              <1> ;swpqs_9:
  4236                              <1> ;	push	edx
  4237                              <1> ;	; eax = page directory
  4238                              <1> ;	; ebx = virtual address
  4239                              <1> ;	call	get_pte
  4240                              <1> ;	mov	ebx, edx	; PTE address
  4241                              <1> ;	pop	edx
  4242                              <1> ;	; 10/06/2016
  4243                              <1> ;	jc	short swpqs_13 ; empty PDE
  4244                              <1> ;	; EAX = PTE value
  4245                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4246                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4247                              <1> ;			        ; from the queue (head)
  4248                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4249                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4250                              <1> ;			        ; from the queue (head) 	
  4251                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4252                              <1> ;	;jnz	short swpqs_11  ; present
  4253                              <1> ;			        ; accessed page
  4254                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4255                              <1> ;	jc	short swpqs_11  ; accessed page
  4256                              <1> ;
  4257                              <1> ;	dec	ecx
  4258                              <1> ;	mov	[swpq_count], cx
  4259                              <1> ;       jz      short swpqs_10
  4260                              <1> ;		; esi = head + 4
  4261                              <1> ;		; edi = head
  4262                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4263                              <1> ;swpqs_10:
  4264                              <1> ;	mov	[edi], ecx ; 0
  4265                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4266                              <1> ;
  4267                              <1> ;swpqs_11:
  4268                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4269                              <1> ;	; Rotation (head -> tail)
  4270                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4271                              <1> ;	jz	short swpqs_10
  4272                              <1> ;		; esi = head + 4
  4273                              <1> ;		; edi = head
  4274                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4275                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4276                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4277                              <1> ;
  4278                              <1> ;	mov	cx, [swpq_count]
  4279                              <1> ;
  4280                              <1> ;swpqs_12:
  4281                              <1> ;	mov	esi, swap_queue ; head
  4282                              <1> ;       jmp     swpqs_7
  4283                              <1> ;
  4284                              <1> ;swpqs_13:
  4285                              <1> ;	dec	ecx
  4286                              <1> ;	mov	[swpq_count], cx
  4287                              <1> ;       jz      swpqs_5
  4288                              <1> ;	jmp	short swpqs_12
  4289                              <1> 
  4290                              <1> ; 17/04/2021
  4291                              <1> ; ('add_to_swp_queue' procedure call is disabled as temporary)
  4292                              <1> 
  4293                              <1> ; 30/11/2021 - temporary !
  4294                              <1> ;add_to_swap_queue:
  4295                              <1> 	; 20/02/2017
  4296                              <1> 	; 20/07/2015
  4297                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4298                              <1> 	;
  4299                              <1> 	; Adds new page to swap queue
  4300                              <1> 	; (page directories and page tables must not be added
  4301                              <1> 	; to swap queue)	
  4302                              <1> 	;
  4303                              <1> 	; INPUT ->
  4304                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4305                              <1> 	;	[u.uno]
  4306                              <1> 	;	20/02/2017
  4307                              <1> 	;	(Linear address = CORE + user's virtual address)
  4308                              <1> 	;
  4309                              <1> 	; OUTPUT ->
  4310                              <1> 	;	EAX = [swpq_count]
  4311                              <1> 	;	      (after the PTE has been added)
  4312                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4313                              <1> 	;	      the PTE could not be added.
  4314                              <1> 	;
  4315                              <1> 	; Modified Registers -> EAX
  4316                              <1> 	;
  4317                              <1> ;	push	ebx
  4318                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4319                              <1> ;	mov	bl, [u.uno] ; current process number
  4320                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4321                              <1> ;				 ; it is already on the queue
  4322                              <1> ;		; then add it to the tail of the queue
  4323                              <1> ;	movzx	eax, word [swpq_count]
  4324                              <1> ;	cmp	ax, 1024
  4325                              <1> ;	jb	short atsq_1
  4326                              <1> ;	sub	ax, ax
  4327                              <1> ;	pop	ebx
  4328                              <1> ;	retn
  4329                              <1> ;atsq_1:
  4330                              <1> ;	push	esi
  4331                              <1> ;	mov	esi, swap_queue
  4332                              <1> ;	and	ax, ax
  4333                              <1> ;	jz	short atsq_2
  4334                              <1> ;	shl	ax, 2	; convert to offset
  4335                              <1> ;	add	esi, eax
  4336                              <1> ;	shr	ax, 2
  4337                              <1> ;atsq_2:
  4338                              <1> ;	inc	ax
  4339                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4340                              <1> ;	mov	[swpq_count], ax
  4341                              <1> ;	pop	esi
  4342                              <1> ;	pop	ebx
  4343                              <1> ;	retn
  4344                              <1> 
  4345                              <1> ; 17/04/2021
  4346                              <1> ; ('unlink_swap_block' procedure call is disabled as temporary)
  4347                              <1> 
  4348                              <1> ; 30/11/2021 - temporary !
  4349                              <1> ;unlink_swap_block:
  4350                              <1> 	; 15/09/2015
  4351                              <1> 	; 30/04/2015
  4352                              <1> 	; 18/04/2015
  4353                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4354                              <1> 	;
  4355                              <1> 	; INPUT -> 
  4356                              <1> 	;	EAX = swap disk/file offset address
  4357                              <1> 	;	      (bit 1 to bit 31)
  4358                              <1> 	; OUTPUT ->
  4359                              <1> 	;	[swpd_free] is increased
  4360                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4361                              <1> 	;
  4362                              <1> 	; Modified Registers -> EAX
  4363                              <1> 	;
  4364                              <1> ;	push	ebx
  4365                              <1> ;	push	edx
  4366                              <1> ;	;
  4367                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4368                              <1> ;				     ; 3 bits right
  4369                              <1> ;				     ; to get swap block/page number
  4370                              <1> ;	mov	edx, eax
  4371                              <1> ;	; 15/09/2015
  4372                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4373                              <1> ;				     ; (1 allocation bit = 1 page)
  4374                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4375                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4376                              <1> ;				     ; (to get 32 bit position)			
  4377                              <1> ;	;
  4378                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4379                              <1> ;	add	ebx, edx
  4380                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4381                              <1> ;				     ; (allocation bit position)	 
  4382                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4383                              <1> ;				     ; than the address in 'swpd_next' ?
  4384                              <1> ;				     ; (next/first free block value)		
  4385                              <1> ;	jnb	short uswpbl_1	     ; no	
  4386                              <1> ;	mov	[swpd_next], eax     ; yes	
  4387                              <1> ;uswpbl_1:
  4388                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4389                              <1> ;				     ; set relevant bit to 1.
  4390                              <1> ;				     ; set CF to the previous bit value	
  4391                              <1> ;	cmc			     ; complement carry flag	
  4392                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4393                              <1> ;				     ; if the block is already deallocated
  4394                              <1> ;				     ; before.	
  4395                              <1> ;       inc     dword [swpd_free]
  4396                              <1> ;uswpbl_2:
  4397                              <1> ;	pop	edx
  4398                              <1> ;	pop	ebx
  4399                              <1> ;	retn
  4400                              <1> 
  4401                              <1> ; 17/04/2021
  4402                              <1> ; ('link_swap_block' procedure call is disabled as temporary)
  4403                              <1> 
  4404                              <1> ; 30/11/2021 - temporary !
  4405                              <1> ;link_swap_block:
  4406                              <1> 	; 01/07/2015
  4407                              <1> 	; 18/04/2015
  4408                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4409                              <1> 	;
  4410                              <1> 	; INPUT -> none
  4411                              <1> 	;
  4412                              <1> 	; OUTPUT ->
  4413                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4414                              <1> 	;	      in sectors (corresponding 
  4415                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4416                              <1> 	;
  4417                              <1> 	;	CF = 1 and EAX = 0 
  4418                              <1> 	; 		   if there is not a free block to be allocated	
  4419                              <1> 	;
  4420                              <1> 	; Modified Registers -> none (except EAX)
  4421                              <1> 	;
  4422                              <1> 
  4423                              <1> ;	;mov	eax, [swpd_free]
  4424                              <1> ;	;and	eax, eax
  4425                              <1> ;	;jz	short out_of_swpspc
  4426                              <1> ;	;
  4427                              <1> ;	push	ebx
  4428                              <1> ;	push	ecx
  4429                              <1> ;	;
  4430                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4431                              <1> ;	mov	ecx, ebx
  4432                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4433                              <1> ;				 ; next_free_swap_block >> 5
  4434                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4435                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4436                              <1> ;lswbl_scan:
  4437                              <1> ;	cmp	ebx, ecx
  4438                              <1> ;	ja	short lswbl_notfound
  4439                              <1> ;	;
  4440                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4441                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4442                              <1> ;			   ; loads the destination with an index to
  4443                              <1> ;			   ; first set bit. (0 -> 31) 
  4444                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4445                              <1> ;	; 01/07/2015
  4446                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4447                              <1> ;			 ;
  4448                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4449                              <1> ;			 ;	  with value of 1 means 
  4450                              <1> ;			 ;	  the corresponding page is free 
  4451                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4452                              <1> ;	add	ebx, 4
  4453                              <1> ;			 ; We return back for searching next page block
  4454                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4455                              <1> ;			 ;	 we always will find at least 1 free block here.
  4456                              <1> ;	jmp    	short lswbl_scan
  4457                              <1> ;	;
  4458                              <1> ;lswbl_notfound:	
  4459                              <1> ;	sub	ecx, swap_alloc_table
  4460                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4461                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4462                              <1> ;	xor	eax, eax
  4463                              <1> ;	mov	[swpd_free], eax
  4464                              <1> ;	stc
  4465                              <1> ;lswbl_ok:
  4466                              <1> ;	pop	ecx
  4467                              <1> ;	pop	ebx
  4468                              <1> ;	retn
  4469                              <1> ;	;
  4470                              <1> ;;out_of_swpspc:
  4471                              <1> ;;	stc
  4472                              <1> ;;	retn
  4473                              <1> ;
  4474                              <1> ;lswbl_found:
  4475                              <1> ;	mov	ecx, ebx
  4476                              <1> ;	sub	ecx, swap_alloc_table
  4477                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4478                              <1> ;				 ; address/offset (to the next)
  4479                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4480                              <1> ;	;
  4481                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4482                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4483                              <1> ;				 ; in the destination.
  4484                              <1> ;				 ;
  4485                              <1> ;				 ; Reset the bit which is corresponding to the 
  4486                              <1> ;				 ; (just) allocated block.
  4487                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4488                              <1> ;	add	eax, ecx	 ; = block number
  4489                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4490                              <1> ;				 ; 1 block =  8 sectors
  4491                              <1> ;	;
  4492                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4493                              <1> ;	;
  4494                              <1> ;	; NOTE: The relevant page table entry will be updated
  4495                              <1> ;	;       according to this EAX value...
  4496                              <1> ;	;
  4497                              <1> ;	jmp	short lswbl_ok
  4498                              <1> 
  4499                              <1> ; 17/04/2021
  4500                              <1> ; ('logical_disk_read' procedure call is disabled as temporary)
  4501                              <1> 
  4502                              <1> ; 30/11/2021 - temporary !
  4503                              <1> ;logical_disk_read:
  4504                              <1> 	; 20/07/2015
  4505                              <1> 	; 09/03/2015 (temporary code here)
  4506                              <1> 	;
  4507                              <1> 	; INPUT ->
  4508                              <1> 	; 	ESI = Logical disk description table address
  4509                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4510                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4511                              <1> 	; 	ECX = Sector count
  4512                              <1> 	;
  4513                              <1> 	;
  4514                              <1> ;	retn
  4515                              <1> 
  4516                              <1> ; 17/04/2021
  4517                              <1> ; ('logical_disk_write' procedure call is disabled as temporary)
  4518                              <1> 
  4519                              <1> ; 30/11/2021 - temporary !
  4520                              <1> ;logical_disk_write:
  4521                              <1> 	; 20/07/2015
  4522                              <1> 	; 09/03/2015 (temporary code here)
  4523                              <1> 	;
  4524                              <1> 	; INPUT ->
  4525                              <1> 	; 	ESI = Logical disk description table address
  4526                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4527                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4528                              <1> 	; 	ECX = Sector count
  4529                              <1> 	;
  4530                              <1> ;	retn
  4531                              <1> 
  4532                              <1> get_physical_addr:
  4533                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  4534                              <1> 	;	(temporary modifications)
  4535                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4536                              <1> 	; 18/10/2015
  4537                              <1> 	; 29/07/2015
  4538                              <1> 	; 20/07/2015
  4539                              <1> 	; 04/06/2015
  4540                              <1> 	; 20/05/2015
  4541                              <1> 	; 28/04/2015
  4542                              <1> 	; 18/04/2015
  4543                              <1> 	; Get physical address
  4544                              <1> 	;     (allocates a new page for user if it is not present)
  4545                              <1> 	;	
  4546                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4547                              <1> 	; (buffer) address to physical address (of the buffer).)
  4548                              <1> 	; ('sys write', 'sys read' system calls...)
  4549                              <1> 	;
  4550                              <1> 	; INPUT ->
  4551                              <1> 	;	EBX = virtual address
  4552                              <1> 	;	u.pgdir = page directory (physical) address
  4553                              <1> 	;
  4554                              <1> 	; OUTPUT ->
  4555                              <1> 	;	EAX = physical address 
  4556                              <1> 	;	EBX = linear address	
  4557                              <1> 	;	EDX = physical address of the page frame
  4558                              <1> 	;	      (with attribute bits)
  4559                              <1> 	;	ECX = byte count within the page frame
  4560                              <1> 	;
  4561                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4562                              <1> 	;
  4563                              <1> 
  4564                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4565 00003254 A1[046F0000]        <1> 	mov	eax, [u.pgdir]
  4566                              <1> 
  4567                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4568                              <1> 	
  4569 00003259 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4570                              <1> 	;
  4571                              <1> 	;mov	eax, [u.pgdir]
  4572 0000325F E816FDFFFF          <1> 	call	get_pte
  4573                              <1> 		; EDX = Page table entry address (if CF=0)
  4574                              <1> 	        ;       Page directory entry address (if CF=1)
  4575                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4576                              <1> 		; EAX = Page table entry value (page address)
  4577                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4578 00003264 731C                <1> 	jnc	short gpa_1
  4579                              <1> 	;
  4580 00003266 E8FDFBFFFF          <1> 	call	allocate_page
  4581 0000326B 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4582                              <1> gpa_0:
  4583 0000326D E867FCFFFF          <1> 	call 	clear_page
  4584                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4585 00003272 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4586                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4587                              <1> 			   ; (user, writable, present page)	
  4588 00003274 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4589 00003276 A1[046F0000]        <1> 	mov	eax, [u.pgdir]	
  4590 0000327B E8FAFCFFFF          <1> 	call	get_pte
  4591 00003280 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4592                              <1> gpa_1:
  4593                              <1> 	; EAX = PTE value, EDX = PTE address
  4594 00003282 A801                <1> 	test 	al, PTE_A_PRESENT
  4595 00003284 750A                <1> 	jnz	short gpa_3
  4596 00003286 09C0                <1> 	or	eax, eax
  4597 00003288 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4598                              <1> 
  4599                              <1> ; 17/04/2021
  4600                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4601 0000328A EB2C                <1> 	jmp	short gpa_im_err  ; temporary !
  4602                              <1> 
  4603                              <1> 	; 20/07/2015
  4604                              <1> ;	push	ebp
  4605                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4606                              <1> ;	; reload swapped page
  4607                              <1> ;	call	reload_page ; 28/04/2015
  4608                              <1> ;	pop	ebp
  4609                              <1> ;	jc	short gpa_retn
  4610                              <1> gpa_2:
  4611                              <1> ; 17/04/2021
  4612                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  4613                              <1> 
  4614                              <1> 	; 20/07/2015
  4615                              <1> 	; 20/05/2015
  4616                              <1> 	; add this page to swap queue
  4617                              <1> ;	push	eax 
  4618                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4619                              <1> ;	call 	add_to_swap_queue
  4620                              <1> ;	pop	eax
  4621                              <1> 		; PTE address in EDX
  4622                              <1> 		; virtual address in EBX
  4623                              <1> 
  4624                              <1> 	; EAX = memory page address
  4625 0000328C 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4626                              <1> 				  ; present flag, bit 0 = 1
  4627                              <1> 				  ; user flag, bit 2 = 1	
  4628                              <1> 				  ; writable flag, bit 1 = 1
  4629 0000328E 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4630                              <1> gpa_3:
  4631                              <1> 	; 18/10/2015
  4632 00003290 89D9                <1> 	mov	ecx, ebx
  4633 00003292 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4634 00003298 89C2                <1> 	mov 	edx, eax
  4635 0000329A 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4636 0000329E 01C8                <1> 	add	eax, ecx
  4637 000032A0 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4638 000032A2 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4639 000032A8 F8                  <1> 	clc
  4640                              <1> gpa_retn:
  4641 000032A9 C3                  <1> 	retn	
  4642                              <1> gpa_4:	
  4643 000032AA E8B9FBFFFF          <1> 	call	allocate_page
  4644 000032AF 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4645 000032B1 E823FCFFFF          <1> 	call	clear_page
  4646 000032B6 EBD4                <1> 	jmp	short gpa_2
  4647                              <1> 
  4648                              <1> gpa_im_err:	
  4649 000032B8 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4650                              <1> 				  ; Major error = 0 (No protection fault)	
  4651 000032BD C3                  <1> 	retn
  4652                              <1> 
  4653                              <1> ; 17/04/2021
  4654                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4655                              <1> 
  4656                              <1> ; 30/11/2021 - temporary !
  4657                              <1> ;reload_page:
  4658                              <1> 	; 20/07/2015
  4659                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4660                              <1> 	;
  4661                              <1> 	; Reload (Restore) swapped page at memory
  4662                              <1> 	;
  4663                              <1> 	; INPUT -> 
  4664                              <1> 	;	EBP = Virtual (linear) memory address
  4665                              <1> 	;	EAX = PTE value (swap disk sector address)
  4666                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4667                              <1> 	; OUTPUT ->
  4668                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4669                              <1> 	;
  4670                              <1> 	;	CF = 1 and EAX = error code
  4671                              <1> 	;
  4672                              <1> 	; Modified Registers -> none (except EAX)
  4673                              <1> 	;
  4674                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4675                              <1> ;	push	ebx      ;
  4676                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4677                              <1> ;	call	allocate_page
  4678                              <1> ;	jc	short rlp_im_err
  4679                              <1> ;	xchg 	eax, ebx	
  4680                              <1> ;	; EBX = Physical memory (page) address
  4681                              <1> ;	; EAX = Swap disk (offset) address
  4682                              <1> ;	; EBP = Virtual (linear) memory address
  4683                              <1> ;	call	swap_in
  4684                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4685                              <1> ;	mov	eax, ebx	
  4686                              <1> ;rlp_retn:
  4687                              <1> ;	pop	ebx
  4688                              <1> ;	retn
  4689                              <1> ;	
  4690                              <1> ;rlp_im_err:	
  4691                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4692                              <1> ;				  ; Major error = 0 (No protection fault)	
  4693                              <1> ;	jmp	short rlp_retn
  4694                              <1> ;
  4695                              <1> ;rlp_swp_err:
  4696                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4697                              <1> ;	jmp	short rlp_retn
  4698                              <1> 
  4699                              <1> copy_page_dir:
  4700                              <1> 	; 17/04/2021 (temporary modifications)
  4701                              <1> 	; 19/09/2015
  4702                              <1> 	; temporary - 07/09/2015
  4703                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4704                              <1> 	;
  4705                              <1> 	; INPUT -> 
  4706                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4707                              <1> 	;		    page directory.
  4708                              <1> 	; OUTPUT ->
  4709                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4710                              <1> 	;	       page directory.
  4711                              <1> 	;	(New page directory with new page table entries.)
  4712                              <1> 	;	(New page tables with read only copies of the parent's
  4713                              <1> 	;	pages.)
  4714                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4715                              <1> 	;
  4716                              <1> 	; Modified Registers -> none (except EAX)
  4717                              <1> 	;
  4718 000032BE E8A5FBFFFF          <1> 	call	allocate_page
  4719 000032C3 723E                <1> 	jc	short cpd_err
  4720                              <1> 	;
  4721 000032C5 55                  <1> 	push	ebp ; 20/07/2015
  4722 000032C6 56                  <1> 	push	esi
  4723 000032C7 57                  <1> 	push	edi
  4724 000032C8 53                  <1> 	push	ebx
  4725 000032C9 51                  <1> 	push	ecx
  4726 000032CA 8B35[046F0000]      <1> 	mov	esi, [u.pgdir]
  4727 000032D0 89C7                <1> 	mov	edi, eax
  4728 000032D2 50                  <1> 	push	eax ; save child's page directory address
  4729                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4730                              <1> 	; (use same system space for all user page tables) 
  4731 000032D3 A5                  <1> 	movsd
  4732 000032D4 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4733 000032D9 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4734                              <1> cpd_0:	
  4735 000032DE AD                  <1> 	lodsd
  4736                              <1> 	;or	eax, eax
  4737                              <1>         ;jnz	short cpd_1
  4738 000032DF A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4739 000032E1 7508                <1> 	jnz	short cpd_1
  4740                              <1>  	; (virtual address at the end of the page table)	
  4741 000032E3 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4742 000032E9 EB0F                <1> 	jmp	short cpd_2
  4743                              <1> cpd_1:	
  4744 000032EB 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4745 000032EF 89C3                <1> 	mov	ebx, eax
  4746                              <1> 	; EBX = Parent's page table address
  4747 000032F1 E81F000000          <1> 	call	copy_page_table
  4748 000032F6 720C                <1> 	jc	short cpd_p_err
  4749                              <1> 	; EAX = Child's page table address
  4750 000032F8 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4751                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4752                              <1> 			 ; (present, writable, user)
  4753                              <1> cpd_2:
  4754 000032FA AB                  <1> 	stosd
  4755 000032FB E2E1                <1> 	loop	cpd_0
  4756                              <1> 	;
  4757 000032FD 58                  <1> 	pop	eax  ; restore child's page directory address
  4758                              <1> cpd_3:
  4759 000032FE 59                  <1> 	pop	ecx
  4760 000032FF 5B                  <1> 	pop	ebx
  4761 00003300 5F                  <1> 	pop	edi
  4762 00003301 5E                  <1> 	pop	esi
  4763 00003302 5D                  <1> 	pop	ebp
  4764                              <1> cpd_err:
  4765 00003303 C3                  <1> 	retn
  4766                              <1> cpd_p_err:
  4767                              <1> 	; release the allocated pages missing (recover free space)
  4768 00003304 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4769 00003305 8B1D[046F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4770 0000330B E888FCFFFF          <1> 	call 	deallocate_page_dir
  4771 00003310 29C0                <1> 	sub	eax, eax ; 0
  4772 00003312 F9                  <1> 	stc
  4773 00003313 EBE9                <1> 	jmp	short cpd_3	
  4774                              <1> 
  4775                              <1> copy_page_table:
  4776                              <1> 	; 17/04/2021 (temporary modifications)
  4777                              <1> 	; 19/09/2015
  4778                              <1> 	; temporary - 07/09/2015
  4779                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4780                              <1> 	;
  4781                              <1> 	; INPUT -> 
  4782                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4783                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4784                              <1> 	; OUTPUT ->
  4785                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4786                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4787                              <1> 	;	CF = 1 -> error 
  4788                              <1> 	;
  4789                              <1> 	; Modified Registers -> EBP (except EAX)
  4790                              <1> 	;
  4791 00003315 E84EFBFFFF          <1> 	call	allocate_page
  4792 0000331A 7244                <1> 	jc	short cpt_err
  4793                              <1> 	;
  4794 0000331C 50                  <1> 	push	eax ; *
  4795                              <1> 	;push 	ebx
  4796 0000331D 56                  <1> 	push	esi
  4797 0000331E 57                  <1> 	push	edi
  4798 0000331F 52                  <1> 	push	edx
  4799 00003320 51                  <1> 	push	ecx
  4800                              <1> 	;
  4801 00003321 89DE                <1> 	mov	esi, ebx
  4802 00003323 89C7                <1> 	mov	edi, eax
  4803 00003325 89C2                <1> 	mov	edx, eax
  4804 00003327 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4805                              <1> cpt_0:
  4806 0000332D AD                  <1> 	lodsd
  4807 0000332E A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4808                              <1> 	;jnz	short cpt_1 (*)
  4809                              <1> 	; 17/04/2021 (temporary (*)
  4810                              <1> 	;and	eax, eax (*)
  4811 00003330 741E                <1> 	jz	short cpt_2  ; 17/04/2021
  4812                              <1> 	
  4813                              <1> ; 17/04/2021
  4814                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4815                              <1> ;
  4816                              <1> ;	; ebp = virtual (linear) address of the memory page
  4817                              <1> ;	call	reload_page ; 28/04/2015
  4818                              <1> ;	jc	short cpt_p_err
  4819                              <1> cpt_1:
  4820 00003332 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4821 00003336 89C1                <1> 	mov	ecx, eax
  4822                              <1> 	; Allocate a new page for the child process
  4823 00003338 E82BFBFFFF          <1> 	call	allocate_page
  4824 0000333D 721C                <1> 	jc	short cpt_p_err
  4825 0000333F 57                  <1> 	push	edi
  4826 00003340 56                  <1> 	push	esi
  4827 00003341 89CE                <1> 	mov	esi, ecx
  4828 00003343 89C7                <1> 	mov	edi, eax
  4829 00003345 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4830 0000334A F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4831 0000334C 5E                  <1> 	pop	esi
  4832 0000334D 5F                  <1> 	pop	edi
  4833                              <1> 	; 
  4834                              <1> ; 17/04/2021
  4835                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)	
  4836                              <1> ;
  4837                              <1> ;	push	ebx
  4838                              <1> ;	push	eax
  4839                              <1> ;	mov	ebx, ebp
  4840                              <1> ;	; ebx = virtual address of the memory page
  4841                              <1> ;	call	add_to_swap_queue
  4842                              <1> ;	pop	eax
  4843                              <1> ;	pop	ebx
  4844                              <1> 	;
  4845                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4846 0000334E 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4847                              <1> cpt_2:
  4848 00003350 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4849                              <1> 	;
  4850 00003351 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4851                              <1> 	;
  4852 00003357 39D7                <1> 	cmp	edi, edx
  4853 00003359 72D2                <1> 	jb	short cpt_0
  4854                              <1> cpt_p_err:
  4855 0000335B 59                  <1> 	pop	ecx
  4856 0000335C 5A                  <1> 	pop	edx
  4857 0000335D 5F                  <1> 	pop	edi
  4858 0000335E 5E                  <1> 	pop	esi
  4859                              <1> 	;pop	ebx
  4860 0000335F 58                  <1> 	pop	eax ; *
  4861                              <1> cpt_err:
  4862 00003360 C3                  <1> 	retn
  4863                              <1> 
  4864                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4865                              <1> 
  4866                              <1> ;; Data:
  4867                              <1> 
  4868                              <1> ; 09/03/2015
  4869                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4870                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4871                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  4872                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4873                              <1> ;swpd_next:  dd 0 ; next free page block
  4874                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2074                                  %include 'sysdefs.s' ; 09/03/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 - SYSDEFS.INC
  2079                              <1> ; Last Modification: 10/01/2022
  2080                              <1> ;
  2081                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2082                              <1> ; (Modified from 
  2083                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2084                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2085                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2086                              <1> ; ----------------------------------------------------------------------------
  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> ; ****************************************************************************
  2094                              <1> 
  2095                              <1> nproc 	equ	16  ; number of processes
  2096                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2097                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2098                              <1> nfiles  equ	50  ; NFILES equ 50 ; 02/01/2022
  2099                              <1> 
  2100                              <1> ; 27/12/2021
  2101                              <1> ;NFILES	  equ   32  ; temporary ! ( 27/12/2021)
  2102                              <1> ; 02/01/2022
  2103                              <1> ;OPENFILES equ	10  ; open files (for user) ; 28/03/2020
  2104                              <1> 
  2105                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2106                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2107                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2108                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2109                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2110                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2111                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2112                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2113                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2114                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2115                              <1> 	; '/core' dump file size = 32768 bytes
  2116                              <1>  
  2117                              <1> ; 08/03/2014 
  2118                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)
  2119                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2120                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2121                              <1> 
  2122                              <1> ; 30/08/2013
  2123                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2124                              <1> 
  2125                              <1> ; 05/02/2014
  2126                              <1> ; process status
  2127                              <1> ;SFREE 	equ 0
  2128                              <1> ;SRUN	equ 1
  2129                              <1> ;SWAIT	equ 2
  2130                              <1> ;SZOMB	equ 3
  2131                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2132                              <1> 
  2133                              <1> ; 09/03/2015
  2134                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2135                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2136                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2137                              <1> 
  2138                              <1> ; 17/09/2015
  2139                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2140                              <1> 
  2141                              <1> ; 21/09/2015 (36) 
  2142                              <1> ; 01/07/2015 (35)
  2143                              <1> ; 14/07/2013 (0-34)
  2144                              <1> ; UNIX v1 system calls
  2145                              <1> _rele 	equ 0
  2146                              <1> _exit 	equ 1
  2147                              <1> _fork 	equ 2
  2148                              <1> _read 	equ 3
  2149                              <1> _write	equ 4
  2150                              <1> _open	equ 5
  2151                              <1> _close 	equ 6
  2152                              <1> _wait 	equ 7
  2153                              <1> _creat 	equ 8
  2154                              <1> _link 	equ 9
  2155                              <1> _unlink	equ 10
  2156                              <1> _exec	equ 11
  2157                              <1> _chdir	equ 12
  2158                              <1> _time 	equ 13
  2159                              <1> _mkdir 	equ 14
  2160                              <1> _chmod	equ 15
  2161                              <1> _chown	equ 16
  2162                              <1> _break	equ 17
  2163                              <1> _stat	equ 18
  2164                              <1> _seek	equ 19
  2165                              <1> _tell 	equ 20
  2166                              <1> _mount	equ 21
  2167                              <1> _umount	equ 22
  2168                              <1> _setuid	equ 23
  2169                              <1> _getuid	equ 24
  2170                              <1> _stime	equ 25
  2171                              <1> _quit	equ 26	
  2172                              <1> _intr	equ 27
  2173                              <1> _fstat	equ 28
  2174                              <1> _emt 	equ 29
  2175                              <1> _mdate 	equ 30
  2176                              <1> _stty 	equ 31
  2177                              <1> _gtty	equ 32
  2178                              <1> _ilgins	equ 33
  2179                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2180                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2181                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2182                              <1> 
  2183                              <1> %macro sys 1-4
  2184                              <1>     ; 13/04/2015
  2185                              <1>     ; Retro UNIX 386 v1 system call.
  2186                              <1>     mov eax, %1
  2187                              <1>     %if %0 >= 2   
  2188                              <1>         mov ebx, %2
  2189                              <1>         %if %0 >= 3    
  2190                              <1>             mov ecx, %3
  2191                              <1>             %if %0 = 4
  2192                              <1>                mov edx, %4   
  2193                              <1>             %endif
  2194                              <1>         %endif
  2195                              <1>     %endif
  2196                              <1>     int 30h	   
  2197                              <1> %endmacro
  2198                              <1> 
  2199                              <1> ; 13/05/2015 - ERROR CODES
  2200                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2201                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2202                              <1> ; 14/05/2015
  2203                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2204                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2205                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2206                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error
  2207                              <1> ; 16/05/2015		
  2208                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2209                              <1> ; 18/05/2015
  2210                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2211                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2212                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2213                              <1> ; 07/06/2015
  2214                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2215                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2216                              <1> ; 09/06/2015
  2217                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2218                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2219                              <1> ; 16/06/2015
  2220                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2221                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2222                              <1> ; 22/06/2015
  2223                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2224                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2225                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2226                              <1> ; 23/06/2015
  2227                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2228                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2229                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2230                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2231                              <1> ; 27/06/2015
  2232                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2233                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2234                              <1> ; 29/06/2015
  2235                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error
  2236                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2237                              <1> 
  2238                              <1> ; 26/08/2015
  2239                              <1> ; 24/07/2015
  2240                              <1> ; 24/06/2015
  2241                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2242                              <1> ; 01/07/2015
  2243                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2244                              <1> ;
  2245                              <1> ; 26/11/2021 ('no free blocks on disk !' error)
  2246                              <1> ERR_ALLOC	   equ 33  ; 'disk allocation error !'	
  2247                              <1> ; 22/11/2021
  2248                              <1> ERR_READ_ONLY_FS   equ 30  ; 'read only file system !' error
  2249                              <1> ; 28/11/2021
  2250                              <1> ERR_INV_FILE	   equ 255 ; 'invalid file (inode) !' error
  2251                              <1> ; 04/12/2021
  2252                              <1> ERR_PERM_DENIED	   equ 11  ; 'permission denied !' error
  2253                              <1> ; 11/12/2021
  2254                              <1> ERR_INV_FUNC	   equ 1   ; 'invalid system call !' error
  2255                              <1> ; 10/01/2022
  2256                              <1> ERR_INO_ALLOC	   equ 33  ; 'inode allocation error !'
  2257                              <1> ERR_NOT_REGULAR    equ 255 ; 'not regular file directory !' error		   					 		
  2075                                  %include 'u0.s'      ; 15/03/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) - SYS0.INC
  2080                              <1> ; Last Modification: 08/01/2022
  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 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2091                              <1> ;
  2092                              <1> ; ****************************************************************************
  2093                              <1> 
  2094                              <1> sys_init:
  2095                              <1> 	; 08/01/2022
  2096                              <1> 	; 01/01/2022
  2097                              <1> 	; 26/12/2021
  2098                              <1> 	; 27/11/2021
  2099                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 (test) compatibility modification
  2100                              <1> 	; 18/10/2015
  2101                              <1> 	; 28/08/2015
  2102                              <1> 	; 24/08/2015
  2103                              <1> 	; 14/08/2015
  2104                              <1> 	; 24/07/2015 
  2105                              <1> 	; 02/07/2015
  2106                              <1> 	; 01/07/2015
  2107                              <1> 	; 23/06/2015
  2108                              <1> 	; 15/04/2015
  2109                              <1> 	; 13/04/2015
  2110                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2111                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2112                              <1> 	;
  2113                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2114                              <1> 	;
  2115                              <1> 	;; 14/02/2014
  2116                              <1> 	;; 14/07/2013
  2117                              <1> 	;mov	ax, 41
  2118                              <1> 	;mov	[rootdir], ax
  2119                              <1> 	;mov	[u.cdir], ax
  2120                              <1> 	;and	al, 1 ; 15/04/2015
  2121                              <1> 	
  2122                              <1> 	; 27/11/2021
  2123                              <1> 	; 18/04/2021 - Retro UNIX 386 v2
  2124 00003361 31C0                <1> 	xor	eax, eax
  2125                              <1> 	; 12/12/2021 - Temporary
  2126 00003363 A2[E06B0000]        <1> 	mov	[p.ttyc], al ; 0  ; test !!!
  2127 00003368 FEC0                <1> 	inc	al	; eax = 1 (root directory inode) ; runix v2 fs
  2128 0000336A A3[8C6E0000]        <1> 	mov	[rootdir], eax ; = 1 ; 28/10/2021 (32 bit)
  2129 0000336F A3[A86E0000]        <1> 	mov	[u.cdir], eax ; 28/10/2021 (32 bit)
  2130                              <1> 
  2131 00003374 A2[F56E0000]        <1> 	mov	[u.uno], al ; = 1
  2132                              <1> 	;mov	[mpid], ax ; 1 
  2133                              <1> 	;mov	[p.pid], ax ; 1
  2134                              <1> 	; 01/01/2022
  2135 00003379 A2[8A6E0000]        <1> 	mov	[mpid], al
  2136 0000337E A2[806B0000]        <1> 	mov	[p.pid], al
  2137 00003383 A2[106C0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2138                              <1> 	;
  2139 00003388 B004                <1> 	mov	al, time_count ; 30/08/2013
  2140 0000338A A2[EC6E0000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2141                              <1> 	; 02/07/2015
  2142 0000338F A1[A86D0000]        <1> 	mov	eax, [k_page_dir]
  2143 00003394 A3[046F0000]        <1> 	mov	[u.pgdir], eax ; reset
  2144                              <1> 	; 18/10/2015
  2145                              <1> 	;sub	eax, eax
  2146                              <1> 	;mov	[u.ppgdir], eax ; 0
  2147                              <1>         ;
  2148 00003399 E82B030000          <1>  	call	epoch
  2149 0000339E A3[486F0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2150                              <1> 	; 17/07/2013
  2151 000033A3 E883060000          <1> 	call 	bf_init ; buffer initialization 
  2152                              <1> 	; 23/06/2015
  2153 000033A8 E8BBFAFFFF          <1> 	call	allocate_page
  2154                              <1> 	;;jc	error
  2155                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2156                              <1> 	; 05/12/2021
  2157 000033AD 7305                <1> 	jnc	short sysinit_1
  2158 000033AF E990000000          <1> 	jmp	panic
  2159                              <1> sysinit_1:
  2160 000033B4 A3[006F0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2161 000033B9 A3[206C0000]        <1> 	mov	[p.upage], eax
  2162                              <1> 	;
  2163 000033BE E816FBFFFF          <1> 	call	clear_page
  2164                              <1> 	;
  2165                              <1> 	; 14/08/2015
  2166 000033C3 FA                  <1> 	cli
  2167                              <1> 	; 14/03/2015
  2168                              <1> 	; 17/01/2014
  2169 000033C4 E8CD010000          <1> 	call	sp_init ; serial port initialization
  2170                              <1> 	; 14/08/2015
  2171 000033C9 FB                  <1> 	sti
  2172                              <1> 	;
  2173                              <1> 	; 30/06/2015
  2174                              <1> 	;mov	esi, kernel_init_ok_msg
  2175                              <1> 	;call 	print_msg
  2176                              <1> 	;
  2177 000033CA 30DB                <1> 	xor	bl, bl ; video page 0
  2178                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2179 000033CC E8FF2F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2180 000033D1 FEC3                <1> 	inc	bl
  2181 000033D3 80FB08              <1> 	cmp	bl, 8
  2182 000033D6 72F4                <1> 	jb	short vp_clr_nxt
  2183                              <1> 	;
  2184                              <1> 	; 24/07/2015
  2185                              <1> 	;push	KDATA
  2186                              <1>         ;push	esp
  2187                              <1> 	;mov	[tss.esp0], esp
  2188                              <1>         ;mov	word [tss.ss0], KDATA
  2189                              <1> 	;
  2190                              <1> 	; 08/01/2022
  2191                              <1> 	; 24/08/2015
  2192                              <1> 	;; temporary (01/07/2015)
  2193                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2194                              <1> 	;		       ; it is not needed here !
  2195                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2196 000033D8 FE0D[9A6E0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2197                              <1> 			      ; 0 = executing a system call
  2198                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2199                              <1> 	;
  2200                              <1> 	;;; 06/08/2015
  2201                              <1> 	;;;call	getch ; wait for a key stroke
  2202                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2203                              <1> ;;sys_init_msg_wait:
  2204                              <1> ;;	push 	ecx
  2205                              <1> ;;	mov	al, 1
  2206                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2207                              <1> ;;	call	getc_n
  2208                              <1> ;;	pop	ecx
  2209                              <1> ;;	jnz	short sys_init_msg_ok
  2210                              <1> ;;	loop	sys_init_msg_wait
  2211                              <1> 	;
  2212                              <1> ;;sys_init_msg_ok:
  2213                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2214 000033DE 6A10                <1> 	push	KDATA ; ss
  2215 000033E0 54                  <1> 	push	esp
  2216 000033E1 9C                  <1> 	pushfd
  2217 000033E2 6A08                <1> 	push	KCODE ; cs
  2218 000033E4 68[11340000]        <1> 	push	init_exec ; eip
  2219 000033E9 8925[9C6E0000]      <1> 	mov	[u.sp], esp
  2220 000033EF 1E                  <1> 	push	ds
  2221 000033F0 06                  <1> 	push	es
  2222 000033F1 0FA0                <1> 	push	fs
  2223 000033F3 0FA8                <1> 	push	gs	
  2224 000033F5 60                  <1> 	pushad
  2225 000033F6 8925[A06E0000]      <1> 	mov	[u.usp], esp
  2226 000033FC E873190000          <1> 	call	wswap ; save current user (u) structure, user registers
  2227                              <1> 		      ; and interrupt return components (for IRET)
  2228 00003401 61                  <1> 	popad
  2229 00003402 6658                <1> 	pop	ax ; gs
  2230 00003404 6658                <1> 	pop	ax ; fs
  2231 00003406 6658                <1> 	pop	ax ; es
  2232 00003408 6658                <1> 	pop	ax ; ds	
  2233 0000340A 58                  <1> 	pop	eax ; eip (init_exec)
  2234 0000340B 6658                <1> 	pop	ax ; cs (KCODE)
  2235 0000340D 58                  <1> 	pop	eax ; E-FLAGS
  2236 0000340E 58                  <1> 	pop	eax ; esp
  2237 0000340F 6658                <1> 	pop	ax ; ss (KDATA)
  2238                              <1> 	;
  2239                              <1> 	; 26/12/2021 ([u.ppgdir] is zero already)
  2240                              <1> 	;xor	eax, eax ; 0
  2241                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2242                              <1> 	;
  2243                              <1> 	; 02/07/2015
  2244                              <1> 	; [u.pgdir ] = [k_page_dir]
  2245                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2246                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2247                              <1> init_exec:
  2248                              <1> 
  2249                              <1> ; temporary - 27/12/2021
  2250                              <1> ; clear faulty areas
  2251                              <1> ;mov ecx, (NFILES*16)/4	
  2252                              <1> ;mov edi, fsp
  2253 00003411 31C0                <1> xor eax, eax
  2254                              <1> ;rep stosd
  2255                              <1> ;mov edi, u.fp
  2256                              <1> ;mov cl, 10
  2257                              <1> ;rep stosb
  2258 00003413 A3[406B0000]        <1> mov [fsp], eax	
  2259                              <1> 
  2260                              <1> 	; 13/03/2013
  2261                              <1> 	; 24/07/2013
  2262 00003418 BB[3A340000]        <1> 	mov	ebx, init_file
  2263 0000341D B9[32340000]        <1> 	mov	ecx, init_argp
  2264                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2265                              <1> 	; ECX contains address of argument list pointer
  2266                              <1> 	;
  2267                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2268                              <1> 			      ; 0 = executing a system call
  2269                              <1> 	sys	_exec  ; execute file
  2184                              <2> 
  2185                              <2> 
  2186 00003422 B80B000000          <2>  mov eax, %1
  2187                              <2>  %if %0 >= 2
  2188                              <2>  mov ebx, %2
  2189                              <2>  %if %0 >= 3
  2190                              <2>  mov ecx, %3
  2191                              <2>  %if %0 = 4
  2192                              <2>  mov edx, %4
  2193                              <2>  %endif
  2194                              <2>  %endif
  2195                              <2>  %endif
  2196 00003427 CD30                <2>  int 30h
  2270 00003429 7319                <1> 	jnc	short panic
  2271                              <1> 	;
  2272 0000342B BE[BC6A0000]        <1> 	mov	esi, etc_init_err_msg
  2273                              <1> 	; 22/11/2021
  2274                              <1> 	;call 	print_msg
  2275 00003430 EB17                <1> 	jmp	short key_to_reboot
  2276                              <1> 
  2277                              <1> ;align 4
  2278                              <1> init_argp:
  2279 00003432 [3A340000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2280                              <1> init_file:
  2281                              <1> 	; 24/08/2015
  2282 0000343A 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2282 00003443 00                  <1>
  2283                              <1> panic:
  2284                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2285                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2286 00003444 BE[A16A0000]        <1> 	mov 	esi, panic_msg
  2287                              <1> key_to_reboot: ; 22/11/2021
  2288 00003449 E819000000          <1> 	call 	print_msg
  2289                              <1> ;key_to_reboot:
  2290                              <1> 	; 15/11/2015
  2291 0000344E E8C92D0000          <1> 	call 	getch 
  2292                              <1> 		; wait for a character from the current tty
  2293                              <1> 	;
  2294 00003453 B00A                <1> 	mov	al, 0Ah
  2295 00003455 8A1D[D66D0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2296 0000345B B407                <1> 	mov	ah, 07h ; Black background, 
  2297                              <1> 			; light gray forecolor
  2298 0000345D E85ADFFFFF          <1> 	call 	write_tty
  2299 00003462 E9F5DBFFFF          <1> 	jmp	cpu_reset 
  2300                              <1> 
  2301                              <1> print_msg:
  2302                              <1> 	; 01/07/2015
  2303                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2304                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2305                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2306                              <1> 	;
  2307                              <1> 	;
  2308 00003467 AC                  <1> 	lodsb
  2309                              <1> pmsg1:
  2310 00003468 56                  <1> 	push 	esi
  2311 00003469 0FB61D[D66D0000]    <1> 	movzx	ebx, byte [ptty]
  2312 00003470 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2313 00003472 E845DFFFFF          <1> 	call 	write_tty
  2314 00003477 5E                  <1> 	pop	esi
  2315 00003478 AC                  <1> 	lodsb
  2316 00003479 20C0                <1> 	and 	al, al
  2317 0000347B 75EB                <1> 	jnz 	short pmsg1
  2318 0000347D C3                  <1> 	retn
  2319                              <1> 	
  2320                              <1> ctrlbrk:
  2321                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2322                              <1> 	; 12/11/2015
  2323                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2324                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2325                              <1> 	;
  2326                              <1> 	; INT 1Bh (control+break) handler		
  2327                              <1> 	;
  2328                              <1>       	; Retro Unix 8086 v1 feature only!
  2329                              <1>       	;
  2330 0000347E 66833D[F06E0000]00  <1> 	cmp 	word [u.intr], 0
  2331 00003486 7641                <1> 	jna 	short cbrk4
  2332                              <1> cbrk0:
  2333                              <1> 	; 12/11/2015
  2334                              <1> 	; 06/12/2013
  2335 00003488 66833D[F26E0000]00  <1> 	cmp 	word [u.quit], 0
  2336 00003490 7437                <1> 	jz	short cbrk4
  2337                              <1> 	;
  2338                              <1> 	; 20/09/2013	
  2339                              <1> 	;push 	ax
  2340                              <1> 	; 04/12/2021
  2341 00003492 50                  <1> 	push	eax
  2342 00003493 A0[D66D0000]        <1> 	mov	al, [ptty]
  2343                              <1> 	;
  2344                              <1> 	; 12/11/2015
  2345                              <1> 	;
  2346                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2347                              <1> 	; or ctrl+break from console (pseudo) tty
  2348                              <1> 	; (!redirection!)
  2349                              <1> 	;
  2350 00003498 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2351 0000349A 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2352                              <1> 	;	
  2353                              <1> 	; Serial port interrupt handler sets [ptty]
  2354                              <1> 	; to the port's tty number (as temporary).
  2355                              <1> 	;
  2356                              <1> 	; If active process is using a stdin or 
  2357                              <1> 	; stdout redirection (by the shell),
  2358                              <1>         ; console tty keyboard must be available
  2359                              <1> 	; to terminate running process,
  2360                              <1> 	; in order to prevent a deadlock. 
  2361                              <1> 	;
  2362 0000349C 52                  <1> 	push	edx
  2363 0000349D 0FB615[F56E0000]    <1> 	movzx	edx, byte [u.uno]
  2364 000034A4 3A82[DF6B0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2365 000034AA 5A                  <1> 	pop	edx
  2366 000034AB 7412                <1> 	je	short cbrk2
  2367                              <1> cbrk1:
  2368 000034AD FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2369                              <1> 	; 06/12/2013
  2370 000034AF 3A05[DA6E0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2371 000034B5 7408                <1> 	je	short cbrk2	
  2372 000034B7 3A05[DB6E0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2373 000034BD 7509                <1> 	jne	short cbrk3	
  2374                              <1> cbrk2:
  2375                              <1> 	;; 06/12/2013
  2376                              <1> 	;mov	ax, [u.quit]
  2377                              <1> 	;and	ax, ax
  2378                              <1> 	;jz	short cbrk3
  2379                              <1> 	;
  2380                              <1> 	;xor	ax, ax ; 0
  2381                              <1> 	;dec	ax
  2382                              <1> 	; 04/12/2021
  2383 000034BF 31C0                <1> 	xor	eax, eax ; 0
  2384 000034C1 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2385                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2386 000034C2 66A3[F26E0000]      <1> 	mov	[u.quit], ax
  2387                              <1> cbrk3:
  2388                              <1> 	;pop	ax
  2389                              <1> 	; 04/12/2021
  2390 000034C8 58                  <1> 	pop	eax
  2391                              <1> cbrk4:
  2392 000034C9 C3                  <1> 	retn
  2393                              <1> 
  2394                              <1> com2_int:
  2395                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2396                              <1> 	; 07/11/2015 
  2397                              <1> 	; 24/10/2015
  2398                              <1> 	; 23/10/2015
  2399                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2400                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2401                              <1> 	; < serial port 2 interrupt handler >
  2402                              <1> 	;
  2403 000034CA 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2404                              <1> 	;;push	eax
  2405                              <1> 	; 08/01/2022
  2406 000034CD 29C0                <1> 	sub	eax, eax
  2407 000034CF B009                <1> 	mov	al, 9
  2408                              <1> 	;mov	ax, 9
  2409 000034D1 EB07                <1> 	jmp	short comm_int
  2410                              <1> com1_int:
  2411                              <1> 	; 07/11/2015
  2412                              <1> 	; 24/10/2015
  2413 000034D3 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2414                              <1> 	; 23/10/2015
  2415                              <1> 	;push	eax
  2416                              <1> 	; 08/01/2022
  2417 000034D6 29C0                <1> 	sub	eax, eax
  2418 000034D8 B008                <1> 	mov	al, 8
  2419                              <1> 	;mov	ax, 8
  2420                              <1> comm_int:
  2421                              <1> 	; 08/01/2022
  2422                              <1> 	; 20/11/2015
  2423                              <1> 	; 18/11/2015
  2424                              <1> 	; 17/11/2015
  2425                              <1> 	; 16/11/2015
  2426                              <1> 	; 09/11/2015
  2427                              <1> 	; 08/11/2015
  2428                              <1> 	; 07/11/2015
  2429                              <1> 	; 06/11/2015 (serial4.asm, 'serial')	
  2430                              <1> 	; 01/11/2015
  2431                              <1> 	; 26/10/2015
  2432                              <1> 	; 23/10/2015
  2433 000034DA 53                  <1> 	push	ebx
  2434 000034DB 56                  <1> 	push	esi
  2435 000034DC 57                  <1> 	push	edi
  2436 000034DD 1E                  <1> 	push 	ds
  2437 000034DE 06                  <1> 	push 	es
  2438                              <1> 	; 18/11/2015
  2439 000034DF 0F20DB              <1> 	mov	ebx, cr3
  2440 000034E2 53                  <1> 	push	ebx ; ****
  2441                              <1> 	;
  2442 000034E3 51                  <1> 	push	ecx ; ***
  2443 000034E4 52                  <1> 	push	edx ; **
  2444                              <1> 	;
  2445 000034E5 BB10000000          <1> 	mov	ebx, KDATA
  2446 000034EA 8EDB                <1> 	mov	ds, bx
  2447 000034EC 8EC3                <1> 	mov	es, bx
  2448                              <1> 	;
  2449 000034EE 8B0D[A86D0000]      <1> 	mov	ecx, [k_page_dir]
  2450 000034F4 0F22D9              <1> 	mov	cr3, ecx
  2451                              <1> 	; 20/11/2015
  2452                              <1> 	; Interrupt identification register
  2453 000034F7 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2454                              <1> 	;
  2455 000034FB 3C08                <1> 	cmp 	al, 8 
  2456 000034FD 7702                <1> 	ja 	short com_i0
  2457                              <1> 	;
  2458                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2459                              <1> 	; 20/11/2015
  2460                              <1> 	; 17/11/2015
  2461                              <1> 	; 16/11/2015
  2462                              <1> 	; 15/11/2015
  2463                              <1> 	; 24/10/2015
  2464                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2465                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2466                              <1> 	; < serial port 1 interrupt handler >
  2467                              <1> 	;
  2468 000034FF FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2469                              <1> com_i0:
  2470                              <1> 	;push	eax ; *
  2471                              <1> 	; 07/11/2015
  2472 00003501 A2[166E0000]        <1> 	mov 	byte [ccomport], al
  2473                              <1> 	; 09/11/2015
  2474                              <1> 	;movzx	ebx, ax ; 8 or 9
  2475                              <1> 	; 08/01/2022
  2476 00003506 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2477                              <1> 	; 17/11/2015
  2478                              <1>  	; reset request for response status
  2479 00003508 88A3[0C6E0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2480                              <1> 	;
  2481                              <1> 	; 20/11/2015
  2482 0000350E EC                  <1> 	in	al, dx		; read interrupt id. register
  2483 0000350F EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2484 00003511 2404                <1> 	and	al, 4		; received data available?	
  2485 00003513 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2486                              <1> 	;
  2487                              <1> 	; 20/11/2015
  2488 00003515 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2489 00003518 EC                  <1> 	in	al, dx     	; read character
  2490                              <1> 	;JMP	$+2	   	; I/O DELAY
  2491                              <1> 	; 08/11/2015
  2492                              <1> 	; 07/11/2015
  2493 00003519 89DE                <1> 	mov	esi, ebx 
  2494 0000351B 89DF                <1> 	mov	edi, ebx
  2495 0000351D 81C6[106E0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2496 00003523 81C7[126E0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2497 00003529 8806                <1> 	mov	[esi], al ; received char (current char)
  2498                              <1> 	; query
  2499 0000352B 20C0                <1> 	and	al, al
  2500 0000352D 7527                <1> 	jnz	short com_i2
  2501                              <1>    	; response
  2502                              <1> 	; 17/11/2015
  2503                              <1> 	; set request for response status
  2504 0000352F FE83[0C6E0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2505                              <1> 	;
  2506 00003535 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2507 00003539 EC                  <1> 	in	al, dx	   	; read line status register 
  2508 0000353A EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2509 0000353C 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2510 0000353E 7445                <1> 	jz	short com_eoi 	; no
  2511 00003540 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2512 00003542 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2513 00003546 EE                  <1> 	out	dx, al	   	; send on serial port
  2514                              <1> 	; 17/11/2015
  2515 00003547 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2516 0000354A 7502                <1> 	jne 	short com_i1    ; no
  2517 0000354C 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2518                              <1> com_i1:
  2519                              <1> 	; 17/11/2015
  2520                              <1> 	; reset request for response status (again)
  2521 0000354E FE8B[0C6E0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2522 00003554 EB2F                <1> 	jmp	short com_eoi
  2523                              <1> com_i2:	
  2524                              <1> 	; 08/11/2015
  2525 00003556 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2526 00003558 7417                <1> 	je	short com_i3	; (check for response signal)
  2527                              <1> 	; 07/11/2015
  2528 0000355A 3C04                <1> 	cmp	al, 04h	; EOT
  2529 0000355C 751C                <1> 	jne	short com_i4	
  2530                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2531                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2532                              <1> 	; 08/11/2015
  2533                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2534 0000355E 861D[D66D0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2535 00003564 E815FFFFFF          <1> 	call 	ctrlbrk
  2536 00003569 861D[D66D0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2537                              <1> 	;mov	al, 04h ; EOT
  2538                              <1> 	; 08/11/2015
  2539 0000356F EB09                <1> 	jmp	short com_i4	
  2540                              <1> com_i3:
  2541                              <1> 	; 08/11/2015
  2542                              <1> 	; If 0FFh has been received just after a query
  2543                              <1> 	; (schar, ZERO), it is a response signal.
  2544                              <1> 	; 17/11/2015
  2545 00003571 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2546 00003574 7704                <1> 	ja	short com_i4 ; no
  2547                              <1> 	; reset query status (schar)
  2548 00003576 8807                <1> 	mov	[edi], al ; 0FFh
  2549 00003578 FEC0                <1> 	inc	al ; 0
  2550                              <1> com_i4:
  2551                              <1> 	; 27/07/2014
  2552                              <1> 	; 09/07/2014
  2553 0000357A D0E3                <1> 	shl	bl, 1	
  2554 0000357C 81C3[D86D0000]      <1> 	add	ebx, ttychr
  2555                              <1> 	; 23/07/2014 (always overwrite)
  2556                              <1> 	;;cmp	word [ebx], 0
  2557                              <1> 	;;ja	short com_eoi
  2558                              <1> 	;
  2559 00003582 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2560                              <1> 			    ; scan code = 0
  2561                              <1> com_eoi:
  2562                              <1> 	;mov	al, 20h
  2563                              <1> 	;out	20h, al	   ; end of interrupt
  2564                              <1> 	;
  2565                              <1> 	; 07/11/2015
  2566                              <1>       	;pop	eax ; *
  2567 00003585 A0[166E0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2568                              <1> 	; al = tty number (8 or 9)
  2569 0000358A E8BF180000          <1>         call	wakeup
  2570                              <1> com_iret:
  2571                              <1> 	; 23/10/2015
  2572 0000358F 5A                  <1> 	pop	edx ; **
  2573 00003590 59                  <1> 	pop	ecx ; ***
  2574                              <1> 	; 18/11/2015
  2575                              <1> 	;pop	eax ; ****
  2576                              <1> 	;mov	cr3, eax
  2577                              <1> 	;jmp	iiret
  2578 00003591 E909D4FFFF          <1> 	jmp	iiretp
  2579                              <1> 
  2580                              <1> ;iiretp: ; 01/09/2015
  2581                              <1> ;	; 28/08/2015
  2582                              <1> ;	pop	eax ; (*) page directory
  2583                              <1> ;	mov	cr3, eax
  2584                              <1> ;iiret:
  2585                              <1> ;	; 22/08/2014
  2586                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2587                              <1> ;	out	20h, al	; 8259 PORT
  2588                              <1> ;	;
  2589                              <1> ;	pop	es
  2590                              <1> ;	pop	ds
  2591                              <1> ;	pop	edi
  2592                              <1> ;	pop	esi
  2593                              <1> ;	pop	ebx ; 29/08/2014
  2594                              <1> ;	pop 	eax
  2595                              <1> ;	iretd
  2596                              <1> 
  2597                              <1> sp_init:
  2598                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2599                              <1> 	; 07/11/2015
  2600                              <1> 	; 29/10/2015
  2601                              <1> 	; 26/10/2015
  2602                              <1> 	; 23/10/2015
  2603                              <1> 	; 29/06/2015
  2604                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2605                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2606                              <1> 	; Initialization of Serial Port Communication Parameters
  2607                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2608                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2609                              <1> 	;
  2610                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2611                              <1> 	;
  2612                              <1> 	; INPUT:  (29/06/2015)
  2613                              <1> 	;	AL = 0 for COM1
  2614                              <1> 	;	     1 for COM2
  2615                              <1> 	;	AH = Communication parameters	
  2616                              <1> 	;
  2617                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2618                              <1> 	;	Bit	4	3	2	1	0
  2619                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2620                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2621                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2622                              <1> 	;		11 = even
  2623                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2624                              <1> 	;		Retro UNIX 386 v1 feature only !
  2625                              <1> 	;	Bit	7    6    5  | Baud rate
  2626                              <1> 	;		------------------------
  2627                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2628                              <1> 	;		0    0    1  | 9600 (12)
  2629                              <1> 	;		0    1    0  | 19200 (6) 
  2630                              <1> 	;		0    1	  1  | 38400 (3) 
  2631                              <1> 	;		1    0	  0  | 14400 (8)
  2632                              <1> 	;		1    0	  1  | 28800 (4)
  2633                              <1> 	;		1    1    0  | 57600 (2)
  2634                              <1> 	;		1    1    1  | 115200 (1) 	
  2635                              <1> 	
  2636                              <1> 	; References:	
  2637                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2638                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2639                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2640                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2641                              <1> 	;
  2642                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2643                              <1> 	;
  2644 00003596 BB[126E0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2645 0000359B 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2646                              <1> 	; 29/10/2015
  2647 0000359F 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2648 000035A3 E84F000000          <1> 	call	sp_i3	; call A4	
  2649 000035A8 A880                <1> 	test	al, 80h
  2650 000035AA 740E                <1> 	jz	short sp_i0 ; OK..
  2651                              <1> 		; Error !
  2652                              <1> 	;mov	dx, 3F8h
  2653 000035AC 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2654                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2655                              <1> 	; 08/01/2022
  2656 000035AF B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2657 000035B1 E841000000          <1> 	call	sp_i3	; call A4	
  2658 000035B6 A880                <1> 	test	al, 80h
  2659 000035B8 7508                <1> 	jnz	short sp_i1
  2660                              <1> sp_i0:
  2661                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2662                              <1>         ; (INT 14h initialization code disables interrupts.)
  2663                              <1> 	;
  2664 000035BA C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2665 000035BD E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2666                              <1> sp_i1:
  2667 000035C2 43                  <1> 	inc	ebx
  2668 000035C3 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2669                              <1> 	; 29/10/2015
  2670                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2671                              <1> 	; 08/01/2022
  2672 000035C7 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2673 000035C9 E829000000          <1> 	call	sp_i3	; call A4	
  2674 000035CE A880                <1> 	test	al, 80h
  2675 000035D0 740E                <1> 	jz	short sp_i2 ; OK..
  2676                              <1> 		; Error !
  2677                              <1> 	;mov	dx, 2F8h
  2678 000035D2 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2679                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2680                              <1> 	; 08/01/2022
  2681 000035D5 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2682 000035D7 E81B000000          <1> 	call	sp_i3	; call A4	
  2683 000035DC A880                <1> 	test	al, 80h
  2684 000035DE 7516                <1> 	jnz	short sp_i7
  2685                              <1> sp_i2:
  2686 000035E0 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2687                              <1> sp_i6:
  2688                              <1> 	;; COM2 - enabling IRQ 3
  2689                              <1> 	; 08/01/2022
  2690 000035E3 B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2691                              <1> 	; 07/11/2015
  2692                              <1> 	; 26/10/2015
  2693                              <1> 	;pushf
  2694                              <1> 	;cli
  2695                              <1> 	;;
  2696                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2697                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2698                              <1> 	;in	al, dx 	   		; read register
  2699                              <1> 	;JMP	$+2	   		; I/O DELAY
  2700                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2701                              <1> 	;out	dx, al     		; write back to register
  2702                              <1> 	;JMP	$+2	   		; I/O DELAY
  2703                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2704                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2705                              <1> 	;in	al, dx     		; read register
  2706                              <1> 	;JMP	$+2	   		; I/O DELAY
  2707                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2708                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2709                              <1> 	;out	dx, al 	   		; write back to register
  2710                              <1> 	;JMP	$+2        		; I/O DELAY
  2711                              <1> 	;in	al, 21h    		; read interrupt mask register
  2712                              <1> 	;JMP	$+2	   		; I/O DELAY
  2713                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2714                              <1> 	;out	21h, al    		; write back to register
  2715                              <1> 	;
  2716                              <1> 	; 08/01/2022
  2717 000035E5 9C                  <1> 	pushf
  2718 000035E6 E8AA000000          <1> 	call	sp_i8
  2719                              <1> 	; 23/10/2015
  2720 000035EB B8[CA340000]        <1> 	mov 	eax, com2_int
  2721 000035F0 A3[A33A0000]        <1> 	mov	[com2_irq3], eax
  2722                              <1> 	; 26/10/2015
  2723 000035F5 9D                  <1> 	popf	
  2724                              <1> sp_i7:
  2725 000035F6 C3                  <1> 	retn
  2726                              <1> 
  2727                              <1> sp_i3:
  2728                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2729                              <1> 	; 28/10/2015
  2730 000035F7 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2731 000035F9 B000                <1> 	mov	al, 0
  2732 000035FB EE                  <1> 	out	dx, al			; disable serial port interrupt
  2733 000035FC EB00                <1> 	JMP	$+2			; I/O DELAY
  2734 000035FE 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2735 00003601 B080                <1> 	mov	al, 80h			
  2736 00003603 EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2737                              <1> 	;-----	SET BAUD RATE DIVISOR
  2738                              <1> 	; 26/10/2015
  2739 00003604 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2740                              <1> 					; of the divisor value
  2741 00003607 88C8                <1> 	mov	al, cl	; 1
  2742 00003609 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2743                              <1> 					; 2 = 57600 baud
  2744                              <1> 					; 3 = 38400 baud
  2745                              <1> 					; 6 = 19200 baud
  2746                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2747 0000360A EB00                <1> 	JMP	$+2			; I/O DELAY
  2748 0000360C 28C0                <1> 	sub	al, al
  2749 0000360E FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2750                              <1> 					; of the divisor value
  2751 00003610 EE                  <1> 	out	dx, al ; 0
  2752 00003611 EB00                <1> 	JMP	$+2			; I/O DELAY
  2753                              <1> 	;	
  2754 00003613 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2755                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2756 00003615 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2757 00003618 EE                  <1> 	out	dx, al			
  2758 00003619 EB00                <1> 	JMP	$+2			; I/O DELAY
  2759                              <1> 	; 29/10/2015
  2760 0000361B FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2761 0000361D 30C0                <1> 	xor	al, al			; 0
  2762 0000361F EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2763 00003620 EB00                <1> 	JMP	$+2	
  2764                              <1> sp_i4:
  2765                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2766                              <1> 	; 29/06/2015 (line status after modem status)
  2767 00003622 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2768                              <1> sp_i4s:
  2769 00003625 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2770 00003626 EB00                <1> 	JMP	$+2			; I/O DELAY
  2771 00003628 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2772 0000362A FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2773                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2774 0000362C EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2775                              <1> 	; AL = Line status, AH = Modem status
  2776 0000362D C3                  <1> 	retn
  2777                              <1> 
  2778                              <1> sp_status:
  2779                              <1> 	; 29/06/2015
  2780                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2781                              <1> 	; Get serial port status
  2782 0000362E 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2783 00003632 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2784                              <1> 					; dx = 2FEh for COM2
  2785 00003634 EBEF                <1> 	jmp	short sp_i4s
  2786                              <1> 
  2787                              <1> sp_setp: ; Set serial port communication parameters
  2788                              <1> 	; 08/01/2022
  2789                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2790                              <1> 	; 07/11/2015
  2791                              <1> 	; 29/10/2015
  2792                              <1> 	; 29/06/2015
  2793                              <1> 	; Retro UNIX 386 v1 feature only !	
  2794                              <1> 	;
  2795                              <1> 	; INPUT:
  2796                              <1> 	;	AL = 0 for COM1
  2797                              <1> 	;	     1 for COM2
  2798                              <1> 	;	AH = Communication parameters (*)
  2799                              <1> 	; OUTPUT:
  2800                              <1> 	;	CL = Line status
  2801                              <1> 	;	CH = Modem status
  2802                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2803                              <1> 	;		 'invalid parameter !' 
  2804                              <1> 	;		 	 or
  2805                              <1> 	;		 'device not ready !' error
  2806                              <1> 	;	
  2807                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2808                              <1> 	;	Bit	4	3	2	1	0
  2809                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2810                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2811                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2812                              <1> 	;		11 = even
  2813                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2814                              <1> 	;		Retro UNIX 386 v1 feature only !
  2815                              <1> 	;	Bit	7    6    5  | Baud rate
  2816                              <1> 	;		------------------------
  2817                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2818                              <1> 	;		0    0    1  | 9600 (12)
  2819                              <1> 	;		0    1    0  | 19200 (6) 
  2820                              <1> 	;		0    1	  1  | 38400 (3) 
  2821                              <1> 	;		1    0	  0  | 14400 (8)
  2822                              <1> 	;		1    0	  1  | 28800 (4)
  2823                              <1> 	;		1    1    0  | 57600 (2)
  2824                              <1> 	;		1    1    1  | 115200 (1) 
  2825                              <1> 	;
  2826                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2827                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2828                              <1> 	;
  2829                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2830                              <1> 	;
  2831 00003636 66BAF803            <1> 	mov	dx, 3F8h
  2832 0000363A BB[126E0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2833 0000363F 3C01                <1> 	cmp	al, 1
  2834 00003641 7770                <1> 	ja 	short sp_invp_err
  2835 00003643 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2836 00003645 FECE                <1> 	dec	dh ; 2F8h
  2837 00003647 43                  <1> 	inc	ebx ; COM2 control byte offset
  2838                              <1> sp_setp1:
  2839                              <1> 	; 29/10/2015
  2840 00003648 8823                <1> 	mov	[ebx], ah
  2841 0000364A 0FB6CC              <1> 	movzx 	ecx, ah
  2842 0000364D C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2843 00003650 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2844 00003653 8A81[C2360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2845 00003659 6689C1              <1> 	mov	cx, ax
  2846 0000365C E896FFFFFF          <1> 	call	sp_i3
  2847 00003661 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2848 00003664 A880                <1> 	test	al, 80h
  2849 00003666 740F                <1> 	jz	short sp_setp2
  2850 00003668 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2851                              <1> stp_dnr_err:
  2852 0000366B C705[186F0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2852 00003673 0000                <1>
  2853                              <1> 	; CL = Line status, CH = Modem status
  2854 00003675 F9                  <1> 	stc
  2855 00003676 C3                  <1> 	retn
  2856                              <1> sp_setp2:
  2857 00003677 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2858                              <1>         ;jna	sp_i6
  2859                              <1> 		      ; COM1 (3F?h)
  2860                              <1> 	; 24/12/2021
  2861 0000367A 7705                <1> 	ja	short sp_i5
  2862 0000367C E962FFFFFF          <1> 	jmp	sp_i6
  2863                              <1> sp_i5: 
  2864                              <1> 	; 08/01/2022
  2865 00003681 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2866                              <1> 	; 07/11/2015
  2867                              <1> 	; 26/10/2015
  2868                              <1> 	; 29/06/2015
  2869                              <1> 	;
  2870                              <1> 	;; COM1 - enabling IRQ 4
  2871                              <1> 	;pushf
  2872                              <1> 	;cli
  2873                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2874                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2875                              <1> 	;in	al, dx 	   		; read register
  2876                              <1> 	;JMP	$+2			; I/O DELAY
  2877                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2878                              <1> 	;out	dx, al     		; write back to register
  2879                              <1> 	;JMP	$+2			; I/O DELAY
  2880                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2881                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2882                              <1> 	;in	al, dx     		; read register
  2883                              <1> 	;JMP	$+2			; I/O DELAY
  2884                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2885                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2886                              <1> 	;out	dx, al 	   		; write back to register
  2887                              <1> 	;JMP	$+2        		; I/O DELAY
  2888                              <1> 	;in	al, 21h    		; read interrupt mask register
  2889                              <1> 	;JMP	$+2			; I/O DELAY
  2890                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2891                              <1> 	;out	21h, al    		; write back to register
  2892                              <1> 	;
  2893                              <1> 	; 08/01/2022
  2894 00003683 9C                  <1> 	pushf
  2895 00003684 E80C000000          <1> 	call	sp_i8
  2896                              <1> 	; 23/10/2015
  2897 00003689 B8[D3340000]        <1> 	mov 	eax, com1_int
  2898 0000368E A3[9F3A0000]        <1> 	mov	[com1_irq4], eax
  2899                              <1> 	; 26/10/2015
  2900 00003693 9D                  <1> 	popf
  2901 00003694 C3                  <1> 	retn
  2902                              <1> 
  2903                              <1> sp_i8:
  2904                              <1> 	; 08/01/2022
  2905                              <1> 	;pushf
  2906 00003695 FA                  <1> 	cli
  2907                              <1> 	;
  2908                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2909 00003696 B2FC                <1> 	mov	dl, 0FCh
  2910 00003698 EC                  <1> 	in	al, dx 	   		; read register
  2911 00003699 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2912 0000369B 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2913 0000369D EE                  <1> 	out	dx, al     		; write back to register
  2914 0000369E EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2915                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2916 000036A0 B2F9                <1> 	mov	dl, 0F9h
  2917 000036A2 EC                  <1> 	in	al, dx     		; read register
  2918 000036A3 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2919                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2920 000036A5 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2921 000036A7 EE                  <1> 	out	dx, al 	   		; write back to register
  2922 000036A8 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2923 000036AA E421                <1> 	in	al, 21h    		; read interrupt mask register
  2924 000036AC EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2925                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2926 000036AE 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2927 000036B0 E621                <1> 	out	21h, al    		; write back to register
  2928                              <1> 	;
  2929                              <1> 	;popf	
  2930 000036B2 C3                  <1> 	retn
  2931                              <1> 
  2932                              <1> sp_invp_err:
  2933 000036B3 C705[186F0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2933 000036BB 0000                <1>
  2934 000036BD 31C9                <1> 	xor	ecx, ecx
  2935 000036BF 49                  <1> 	dec	ecx ; 0FFFFh
  2936 000036C0 F9                  <1> 	stc
  2937 000036C1 C3                  <1> 	retn
  2938                              <1> 
  2939                              <1> ; 29/10/2015
  2940                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2941 000036C2 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2942                              <1> 
  2943                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2944                              <1> epoch:
  2945                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2946                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2947                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2948                              <1> 	; 'epoch' procedure prototype: 
  2949                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2950                              <1> 	; 14/11/2012
  2951                              <1> 	; unixboot.asm (boot file configuration)
  2952                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2953                              <1> 	; 21/7/2012
  2954                              <1> 	; 15/7/2012
  2955                              <1> 	; 14/7/2012		
  2956                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2957                              <1> 	; compute current date and time as UNIX Epoch/Time
  2958                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2959                              <1> 	;
  2960                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2961                              <1> 	;
  2962 000036C9 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2963 000036CE 86E9                <1>         xchg 	ch,cl
  2964 000036D0 66890D[166B0000]    <1>         mov 	[hour], cx
  2965 000036D7 86F2                <1>         xchg 	dh,dl
  2966 000036D9 668915[1A6B0000]    <1>         mov 	[second], dx
  2967                              <1> 	;
  2968 000036E0 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2969 000036E5 86E9                <1>         xchg 	ch,cl
  2970 000036E7 66890D[106B0000]    <1>         mov 	[year], cx
  2971 000036EE 86F2                <1>         xchg 	dh,dl
  2972 000036F0 668915[126B0000]    <1>         mov 	[month], dx
  2973                              <1> 	;
  2974 000036F7 66B93030            <1> 	mov 	cx, 3030h
  2975                              <1> 	;
  2976 000036FB A0[166B0000]        <1> 	mov 	al, [hour] ; Hour
  2977                              <1>         	; AL <= BCD number)
  2978 00003700 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2979                              <1> 					; AH = AL / 10h
  2980                              <1> 					; AL = AL MOD 10h
  2981 00003702 D50A                <1>         aad 	; AX= AH*10+AL
  2982 00003704 A2[166B0000]        <1> 	mov 	[hour], al
  2983 00003709 A0[176B0000]        <1> 	mov 	al, [hour+1] ; Minute
  2984                              <1>         	; AL <= BCD number)
  2985 0000370E D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2986                              <1> 					; AH = AL / 10h
  2987                              <1> 					; AL = AL MOD 10h
  2988 00003710 D50A                <1>         aad 	; AX= AH*10+AL
  2989 00003712 A2[186B0000]        <1> 	mov 	[minute], al
  2990 00003717 A0[1A6B0000]        <1> 	mov 	al, [second] ; Second
  2991                              <1>         	; AL <= BCD number)
  2992 0000371C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2993                              <1> 					; AH = AL / 10h
  2994                              <1> 					; AL = AL MOD 10h
  2995 0000371E D50A                <1>         aad 	; AX= AH*10+AL
  2996 00003720 A2[1A6B0000]        <1> 	mov 	[second], al
  2997 00003725 66A1[106B0000]      <1> 	mov 	ax, [year] ; Year (century)
  2998                              <1> 	;push 	ax
  2999                              <1> 	; 04/12/2021
  3000 0000372B 50                  <1> 	push	eax
  3001                              <1> 	   	; AL <= BCD number)
  3002 0000372C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3003                              <1> 					; AH = AL / 10h
  3004                              <1> 					; AL = AL MOD 10h
  3005 0000372E D50A                <1>         aad 	; AX= AH*10+AL
  3006 00003730 B464                <1> 	mov 	ah, 100
  3007 00003732 F6E4                <1> 	mul 	ah
  3008 00003734 66A3[106B0000]      <1> 	mov 	[year], ax
  3009                              <1> 	;pop	ax
  3010                              <1> 	; 04/12/2021
  3011 0000373A 58                  <1> 	pop	eax
  3012 0000373B 88E0                <1> 	mov	al, ah
  3013                              <1>         	; AL <= BCD number)
  3014 0000373D D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3015                              <1> 					; AH = AL / 10h
  3016                              <1> 					; AL = AL MOD 10h
  3017 0000373F D50A                <1>         aad 	; AX= AH*10+AL
  3018 00003741 660105[106B0000]    <1> 	add 	[year], ax
  3019 00003748 A0[126B0000]        <1> 	mov 	al, [month] ; Month
  3020                              <1>            	; AL <= BCD number)
  3021 0000374D D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3022                              <1> 					; AH = AL / 10h
  3023                              <1> 					; AL = AL MOD 10h
  3024 0000374F D50A                <1>         aad 	; AX= AH*10+AL
  3025 00003751 A2[126B0000]        <1> 	mov 	[month], al	
  3026 00003756 A0[136B0000]        <1>         mov     al, [month+1]      	; Day
  3027                              <1>            	; AL <= BCD number)
  3028 0000375B D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3029                              <1> 					; AH = AL / 10h
  3030                              <1> 					; AL = AL MOD 10h
  3031 0000375D D50A                <1>         aad 	; AX= AH*10+AL
  3032 0000375F A2[146B0000]        <1>         mov     [day], al
  3033                              <1> 	
  3034                              <1> convert_to_epoch:
  3035                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3036                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3037                              <1> 	;
  3038                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3039                              <1> 	;
  3040                              <1> 	; Derived from DALLAS Semiconductor
  3041                              <1> 	; Application Note 31 (DS1602/DS1603)
  3042                              <1> 	; 6 May 1998
  3043 00003764 29C0                <1> 	sub 	eax, eax
  3044 00003766 66A1[106B0000]      <1> 	mov 	ax, [year]
  3045 0000376C 662DB207            <1> 	sub 	ax, 1970
  3046 00003770 BA6D010000          <1> 	mov 	edx, 365
  3047 00003775 F7E2                <1> 	mul 	edx
  3048 00003777 31DB                <1> 	xor 	ebx, ebx
  3049 00003779 8A1D[126B0000]      <1> 	mov 	bl, [month]
  3050 0000377F FECB                <1> 	dec 	bl
  3051 00003781 D0E3                <1> 	shl 	bl, 1
  3052                              <1> 	;sub	edx, edx
  3053 00003783 668B93[1C6B0000]    <1> 	mov 	dx, [EBX+DMonth]
  3054 0000378A 8A1D[146B0000]      <1>         mov     bl, [day]
  3055 00003790 FECB                <1> 	dec 	bl
  3056 00003792 01D0                <1> 	add 	eax, edx
  3057 00003794 01D8                <1> 	add 	eax, ebx
  3058                              <1> 			; EAX = days since 1/1/1970
  3059 00003796 668B15[106B0000]    <1> 	mov 	dx, [year]
  3060 0000379D 6681EAB107          <1> 	sub 	dx, 1969
  3061 000037A2 66D1EA              <1> 	shr 	dx, 1
  3062 000037A5 66D1EA              <1> 	shr 	dx, 1		
  3063                              <1> 		; (year-1969)/4
  3064 000037A8 01D0                <1> 	add 	eax, edx
  3065                              <1> 			; + leap days since 1/1/1970
  3066 000037AA 803D[126B0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3067 000037B1 7610                <1> 	jna 	short cte1
  3068 000037B3 668B15[106B0000]    <1> 	mov 	dx, [year]
  3069 000037BA 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3070 000037BE 7503                <1> 	jnz 	short cte1		
  3071                              <1> 			; and if leap year
  3072 000037C0 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3073                              <1> cte1: 			; compute seconds since 1/1/1970
  3074 000037C3 BA18000000          <1> 	mov 	edx, 24
  3075 000037C8 F7E2                <1> 	mul	edx
  3076 000037CA 8A15[166B0000]      <1> 	mov 	dl, [hour]
  3077 000037D0 01D0                <1> 	add 	eax, edx
  3078                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3079                              <1> 	;mov	ebx, 60
  3080 000037D2 B33C                <1> 	mov	bl, 60
  3081 000037D4 F7E3                <1> 	mul	ebx
  3082 000037D6 8A15[186B0000]      <1> 	mov 	dl, [minute]
  3083 000037DC 01D0                <1> 	add 	eax, edx
  3084                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3085                              <1> 	;mov 	ebx, 60
  3086 000037DE F7E3                <1> 	mul	ebx
  3087 000037E0 8A15[1A6B0000]      <1> 	mov 	dl, [second]
  3088 000037E6 01D0                <1> 	add 	eax, edx
  3089                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3090 000037E8 C3                  <1> 	retn
  3091                              <1> 
  3092                              <1> get_rtc_time:
  3093                              <1> 	; 15/03/2015
  3094                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3095                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3096                              <1> 	; INT 1Ah
  3097                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3098                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3099                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3100                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3101                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3102                              <1> 	;								
  3103                              <1> RTC_20: 				; GET RTC TIME
  3104 000037E9 FA                  <1> 	cli
  3105 000037EA E845D3FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3106 000037EF 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3107                              <1> 
  3108 000037F1 B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3109 000037F3 E826D3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3110 000037F8 88C6                <1> 	MOV	DH, AL			; SAVE
  3111 000037FA B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3112 000037FC E81DD3FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3113 00003801 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3114 00003803 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3115 00003805 B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3116 00003807 E812D3FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3117 0000380C 88C1                <1> 	MOV	CL, AL			; SAVE
  3118 0000380E B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3119 00003810 E809D3FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3120 00003815 88C5                <1> 	MOV	CH, AL			; SAVE
  3121 00003817 F8                  <1> 	CLC				; SET CY= 0
  3122                              <1> RTC_29:
  3123 00003818 FB                  <1> 	sti
  3124 00003819 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3125                              <1> 
  3126                              <1> get_rtc_date:
  3127                              <1> 	; 15/03/2015
  3128                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3129                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3130                              <1> 	; INT 1Ah
  3131                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3132                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3133                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3134                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3135                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3136                              <1> 	;
  3137                              <1> RTC_40: 				; GET RTC DATE
  3138 0000381A FA                  <1> 	cli
  3139 0000381B E814D3FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3140 00003820 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3141                              <1> 
  3142 00003822 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3143 00003824 E8F5D2FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3144 00003829 88C2                <1> 	MOV	DL, AL			; SAVE
  3145 0000382B B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3146 0000382D E8ECD2FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3147 00003832 88C6                <1> 	MOV	DH, AL			; SAVE
  3148 00003834 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3149 00003836 E8E3D2FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3150 0000383B 88C1                <1> 	MOV	CL, AL			; SAVE
  3151 0000383D B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3152 0000383F E8DAD2FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3153 00003844 88C5                <1> 	MOV	CH, AL			; SAVE
  3154 00003846 F8                  <1> 	CLC				; SET CY=0
  3155                              <1> RTC_49:
  3156 00003847 FB                  <1> 	sti
  3157 00003848 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3158                              <1> 
  3159                              <1> set_date_time:
  3160                              <1> convert_from_epoch:
  3161                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3162                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3163                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3164                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3165                              <1> 	;
  3166                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3167                              <1> 	;
  3168                              <1> 	; Derived from DALLAS Semiconductor
  3169                              <1> 	; Application Note 31 (DS1602/DS1603)
  3170                              <1> 	; 6 May 1998
  3171                              <1> 	;
  3172                              <1> 	; INPUT:
  3173                              <1> 	; EAX = Unix (Epoch) Time
  3174                              <1> 	;
  3175 00003849 31D2                <1> 	xor 	edx, edx
  3176 0000384B B93C000000          <1> 	mov 	ecx, 60
  3177 00003850 F7F1                <1> 	div	ecx
  3178                              <1> 	;mov 	[imin], eax   ; whole minutes
  3179                              <1> 			  ; since 1/1/1970
  3180 00003852 668915[1A6B0000]    <1> 	mov 	[second], dx  ; leftover seconds
  3181 00003859 29D2                <1> 	sub 	edx, edx
  3182 0000385B F7F1                <1> 	div	ecx
  3183                              <1> 	;mov 	[ihrs], eax   ; whole hours
  3184                              <1> 	;		      ; since 1/1/1970
  3185 0000385D 668915[186B0000]    <1> 	mov 	[minute], dx  ; leftover minutes
  3186 00003864 31D2                <1> 	xor	edx, edx
  3187                              <1> 	;mov 	cx, 24
  3188 00003866 B118                <1> 	mov 	cl, 24
  3189 00003868 F7F1                <1> 	div	ecx
  3190                              <1> 	;mov 	[iday], ax   ; whole days
  3191                              <1> 			     ; since 1/1/1970
  3192 0000386A 668915[166B0000]    <1> 	mov 	[hour], dx   ; leftover hours
  3193 00003871 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3194                              <1> 			     ; 1/1/1968 	
  3195                              <1> 	;mov 	[iday], ax
  3196 00003876 50                  <1> 	push 	eax
  3197 00003877 29D2                <1> 	sub	edx, edx
  3198 00003879 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3199 0000387E F7F1                <1> 	div	ecx
  3200 00003880 59                  <1> 	pop 	ecx
  3201                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3202 00003881 6652                <1> 	push 	dx
  3203                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3204 00003883 6683FA3C            <1> 	cmp 	dx, 31 + 29  ; if past feb 29 then
  3205 00003887 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3206 00003888 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3207                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3208                              <1> 	;mov 	cx, [iday]
  3209 0000388B 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3210 0000388C 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3211 0000388E B96D010000          <1> 	mov 	ecx, 365
  3212 00003893 31D2                <1> 	xor	edx, edx
  3213                              <1> 	; EAX = iday-lday, EDX = 0
  3214 00003895 F7F1                <1> 	div	ecx
  3215                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3216                              <1> 	;jday = iday - (iyrs*365) - lday
  3217                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3218                              <1> 	;add	eax, 1968
  3219 00003897 6605B007            <1> 	add 	ax, 1968     ; compute year
  3220 0000389B 66A3[106B0000]      <1> 	mov 	[year], ax
  3221 000038A1 6689D1              <1> 	mov 	cx, dx
  3222                              <1> 	;mov 	dx, [qday]
  3223 000038A4 665A                <1> 	pop 	dx
  3224 000038A6 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3225 000038AB 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3226 000038AD 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3227 000038B1 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3228 000038B2 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3229                              <1> cfe1:			
  3230                              <1> 	;mov 	[jday], cx
  3231 000038B6 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3232 000038BA 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3233 000038BE 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3234                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3235 000038C2 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3236 000038C5 731D                <1> 	jnb 	short cfe3
  3237 000038C7 664B                <1> 	dec 	bx           ; month = month - 1
  3238 000038C9 66D1E3              <1> 	shl 	bx, 1 
  3239 000038CC 668B93[1C6B0000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3240 000038D3 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3241 000038D6 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3242 000038DA 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3243 000038DC 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3244 000038DE 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3245 000038E0 6642                <1> 	inc 	dx           ; mday = mday + 1
  3246 000038E2 EBDE                <1> 	jmp 	short cfe2
  3247                              <1> cfe3:
  3248 000038E4 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3249 000038E6 66891D[126B0000]    <1> 	mov 	[month], bx
  3250 000038ED 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3251 000038F0 6641                <1> 	inc 	cx 			  
  3252 000038F2 66890D[146B0000]    <1> 	mov 	[day], cx
  3253                              <1> 	
  3254                              <1> 	; eax, ebx, ecx, edx is changed at return
  3255                              <1> 	; output ->
  3256                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3257                              <1> 	
  3258                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3259                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3260                              <1> set_date:
  3261 000038F9 A0[116B0000]        <1>         mov     al, [year+1]
  3262 000038FE D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3263 00003900 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3264                              <1> 			     ; AL = AH * 10h + AL
  3265 00003902 88C5                <1> 	mov 	ch, al ; century (BCD)
  3266 00003904 A0[106B0000]        <1> 	mov 	al, [year]
  3267 00003909 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3268 0000390B D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3269                              <1> 			     ; AL = AH * 10h + AL
  3270 0000390D 88C1                <1> 	mov 	cl, al ; year (BCD)
  3271 0000390F A0[126B0000]        <1>         mov 	al, [month]
  3272 00003914 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3273 00003916 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3274                              <1> 			     ; AL = AH * 10h + AL
  3275 00003918 88C6                <1> 	mov 	dh, al ; month (BCD)
  3276 0000391A A0[146B0000]        <1> 	mov 	al, [day]
  3277 0000391F D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3278 00003921 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3279                              <1> 			     ; AL = AH * 10h + AL
  3280 00003923 88C6                <1> 	mov 	dh, al ; day (BCD)
  3281                              <1> 	; Set real-time clock date
  3282 00003925 E879000000          <1> 	call	set_rtc_date
  3283                              <1> set_time:
  3284                              <1>         ; Read real-time clock time 
  3285                              <1> 	; (get day light saving time bit status)
  3286 0000392A FA                  <1>  	cli
  3287 0000392B E804D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3288                              <1> 	; cf = 1 -> al = 0
  3289 00003930 7207                <1>         jc      short stime1
  3290 00003932 B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3291 00003934 E8E5D1FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3292                              <1> stime1:
  3293 00003939 FB                  <1> 	sti
  3294 0000393A 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3295 0000393C 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3296                              <1> 	; DL = 1 or 0 (day light saving time)
  3297                              <1> 	;	
  3298 0000393E A0[166B0000]        <1> 	mov 	al, [hour]
  3299 00003943 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3300 00003945 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3301                              <1> 			     ; AL = AH * 10h + AL
  3302 00003947 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3303 00003949 A0[186B0000]        <1>         mov     al, [minute]
  3304 0000394E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3305 00003950 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3306                              <1> 			     ; AL = AH * 10h + AL
  3307 00003952 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3308 00003954 A0[1A6B0000]        <1>         mov     al, [second]
  3309 00003959 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3310 0000395B D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3311                              <1> 			     ; AL = AH * 10h + AL
  3312 0000395D 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3313                              <1> 	; Set real-time clock time
  3314                              <1>  	; call	set_rtc_time
  3315                              <1> set_rtc_time:
  3316                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3317                              <1> 	; 15/03/2015
  3318                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3319                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3320                              <1> 	; INT 1Ah
  3321                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3322                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3323                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3324                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3325                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3326                              <1> 	;								:
  3327                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3328                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3329                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3330                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3331                              <1> 	;
  3332                              <1> RTC_30: 				; SET RTC TIME
  3333 0000395F FA                  <1> 	cli
  3334 00003960 E8CFD1FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3335 00003965 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3336 00003967 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3337                              <1> RTC_35:
  3338 0000396C 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3339 0000396E B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3340 00003970 E89E000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3341 00003975 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3342 00003977 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3343 00003979 E895000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3344 0000397E 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3345 00003980 B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3346 00003982 E88C000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3347                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3348 00003987 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3349 0000398B E88ED1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3350 00003990 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3351 00003992 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3352 00003994 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3353 00003997 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3354 00003999 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3355 0000399B E873000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3356 000039A0 F8                  <1> 	CLC				; SET CY= 0
  3357 000039A1 FB                  <1> 	sti
  3358 000039A2 C3                  <1> 	RETn				; RETURN WITH CY= 0
  3359                              <1> 
  3360                              <1> set_rtc_date:
  3361                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3362                              <1> 	; 15/03/2015
  3363                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3364                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3365                              <1> 	; INT 1Ah
  3366                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3367                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3368                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3369                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3370                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3371                              <1> 	;
  3372                              <1> RTC_50: 				; SET RTC DATE
  3373 000039A3 FA                  <1> 	cli
  3374 000039A4 E88BD1FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3375 000039A9 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3376 000039AB E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3377                              <1> RTC_55:
  3378 000039B0 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3379 000039B4 E85A000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3380 000039B9 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3381 000039BB B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3382 000039BD E851000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3383 000039C2 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3384 000039C4 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3385 000039C6 E848000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3386 000039CB 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3387 000039CD B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3388 000039CF E83F000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3389 000039D4 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3390 000039D6 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3391 000039D8 E836000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3392                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3393 000039DD 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3394 000039E1 E838D1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3395 000039E6 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3396 000039E8 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3397 000039EA E824000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3398 000039EF F8                  <1> 	CLC				; SET CY= 0
  3399 000039F0 FB                  <1> 	sti
  3400 000039F1 C3                  <1> 	RETn				; RETURN CY=0
  3401                              <1> 
  3402                              <1> 	; 15/03/2015
  3403                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3404 000039F2 B426                <1> 	mov	ah, 26h
  3405 000039F4 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3406 000039F6 E818000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3407 000039FB B482                <1> 	mov	ah, 82h
  3408 000039FD B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3409 000039FF E80F000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3410 00003A04 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3411 00003A06 E813D1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3412 00003A0B B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3413 00003A0D E80CD1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3414 00003A12 C3                  <1> 	RETn
  3415                              <1> 
  3416                              <1> 	; 15/03/2015
  3417                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3418                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3419 00003A13 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3420                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3421 00003A14 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3422 00003A16 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3423 00003A17 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3424 00003A19 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3425 00003A1A E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3426 00003A1C 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3427 00003A1E E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3428 00003A20 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3429 00003A22 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3430 00003A24 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3431 00003A26 90                  <1> 	nop			; I/O DELAY
  3432 00003A27 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3433                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3434 00003A29 9D                  <1> 	popf	
  3435 00003A2A C3                  <1> 	RETn
  3436                              <1> 
  3437                              <1> bf_init:
  3438                              <1> 	; 28/11/2021
  3439                              <1> 	; 14/08/2015
  3440                              <1> 	; 02/07/2015
  3441                              <1> 	; 01/07/2015
  3442                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3443                              <1> 	; Buffer (pointer) initialization !
  3444                              <1> 	; 
  3445                              <1> 	; 17/07/2013 - 24/07/2013
  3446                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3447                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3448                              <1> 	;
  3449 00003A2B BF[606E0000]        <1> 	mov	edi, bufp 
  3450 00003A30 B8[8C830000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3451 00003A35 29D2                <1> 	sub	edx, edx
  3452 00003A37 FECA                <1> 	dec	dl
  3453 00003A39 31C9                <1> 	xor	ecx, ecx
  3454 00003A3B 49                  <1> 	dec	ecx
  3455                              <1> bi0:
  3456 00003A3C 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3457 00003A41 AB                  <1> 	stosd
  3458 00003A42 89C6                <1> 	mov	esi, eax
  3459 00003A44 8916                <1> 	mov	[esi], edx ; 000000FFh
  3460                              <1> 			    ; Not a valid device sign
  3461 00003A46 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3462                              <1> 		      ; Not a valid block number sign 	 	
  3463 00003A49 3D[5C770000]        <1> 	cmp	eax, buffer
  3464 00003A4E 77EC                <1> 	ja	short bi0
  3465 00003A50 B8[4C6F0000]        <1> 	mov	eax, sb0
  3466 00003A55 AB                  <1> 	stosd
  3467 00003A56 B8[54710000]        <1> 	mov	eax, sb1
  3468 00003A5B AB                  <1> 	stosd
  3469 00003A5C 89C6                <1> 	mov	esi, eax ; offset sb1
  3470 00003A5E 8916                <1> 	mov	[esi], edx ; 000000FFh
  3471                              <1> 			    ; Not a valid device sign
  3472 00003A60 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3473                              <1> 		      ; Not a valid block number sign 	 
  3474                              <1> 	; 14/08/2015
  3475                              <1> 	;call 	rdev_init
  3476                              <1> 	;retn
  3477                              <1> 
  3478                              <1> 	; 28/11/2021
  3479                              <1> rdev_init: ; root device, super block buffer initialization
  3480                              <1> 	; 14/08/2015
  3481                              <1> 	; Retro UNIX 386 v1 feature only !
  3482                              <1> 	;
  3483                              <1> 	; NOTE: Disk partitions (file systems), logical
  3484                              <1> 	; drive initialization, partition's start sector etc.
  3485                              <1> 	; will be coded here, later in 'ldrv_init'	
  3486                              <1> 
  3487 00003A63 0FB605[9A680000]    <1> 	movzx	eax, byte [boot_drv]
  3488                              <1> rdi_0:
  3489 00003A6A 3C80                <1> 	cmp	al, 80h
  3490 00003A6C 7202                <1> 	jb	short rdi_1
  3491 00003A6E 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3492                              <1> rdi_1:
  3493                              <1> ; temporary - 05/12/2021
  3494 00003A70 20C0                <1> and	al, al
  3495 00003A72 7515                <1> jnz	short rdi_2
  3496 00003A74 C605[C0680000]12    <1> mov	byte [drv.spt], 18
  3497 00003A7B C605[B2680000]02    <1> mov	byte [drv.heads], 2
  3498 00003A82 C605[A4680000]50    <1> mov	byte [drv.cylinders], 80
  3499                              <1> rdi_2:
  3500 00003A89 A2[866E0000]        <1> 	mov	[rdev], al
  3501 00003A8E BB[4C6F0000]        <1>         mov	ebx, sb0 ; super block buffer
  3502 00003A93 8903                <1> 	mov 	[ebx], eax
  3503 00003A95 B001                <1> 	mov	al, 1 ; eax = 1
  3504 00003A97 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3505                              <1> 	;call 	diskio
  3506                              <1> 	;retn
  3507                              <1> 	; 28/11/2021
  3508 00003A9A E941260000          <1> 	jmp	diskio
  3509                              <1> 
  3510                              <1> ; 23/10/2015
  3511                              <1> com1_irq4:
  3512 00003A9F [A73A0000]          <1> 	dd dummy_retn
  3513                              <1> com2_irq3:
  3514 00003AA3 [A73A0000]          <1> 	dd dummy_retn
  3515                              <1> 
  3516                              <1> dummy_retn:
  3517 00003AA7 C3                  <1> 	retn
  2076                                  %include 'u1.s'      ; 10/05/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) - SYS1.INC
  2081                              <1> ; Last Modification: 09/01/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 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2092                              <1> ;
  2093                              <1> ; ****************************************************************************
  2094                              <1> 
  2095                              <1> unkni: ; / used for all system calls
  2096                              <1> sysent: ; < enter to system call >
  2097                              <1> 	; 25/12/2021 (Retro UNIX 386 v1.2)
  2098                              <1> 	; 19/10/2015
  2099                              <1> 	; 21/09/2015
  2100                              <1> 	; 01/07/2015
  2101                              <1> 	; 19/05/2015
  2102                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2103                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2104                              <1> 	;
  2105                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2106                              <1> 	; The trap type is determined and an indirect jump is made to 
  2107                              <1> 	; the appropriate system call handler. If there is a trap inside
  2108                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2109                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2110                              <1> 	; instructor is decoded to get the the system code part (see
  2111                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2112                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2113                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2114                              <1> 	; is called. If the call is legitimate control passes to the
  2115                              <1> 	; appropriate system routine.
  2116                              <1> 	;
  2117                              <1> 	; Calling sequence:
  2118                              <1> 	;	Through a trap caused by any sys call outside the system.
  2119                              <1> 	; Arguments:
  2120                              <1> 	;	Arguments of particular system call.	
  2121                              <1> 	; ...............................................................
  2122                              <1> 	;	
  2123                              <1> 	; Retro UNIX 8086 v1 modification: 
  2124                              <1> 	;       System call number is in EAX register.
  2125                              <1> 	;
  2126                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2127                              <1> 	;	registers depending of function details.
  2128                              <1>   	;
  2129                              <1> 	; 16/04/2015
  2130 00003AA8 368925[9C6E0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2131                              <1> 	; save user registers
  2132 00003AAF 1E                  <1> 	push	ds
  2133 00003AB0 06                  <1> 	push	es
  2134 00003AB1 0FA0                <1> 	push	fs
  2135 00003AB3 0FA8                <1> 	push	gs
  2136 00003AB5 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2137                              <1> 	;
  2138                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2139                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2140                              <1> 	;	for saving/restoring user registers.)
  2141                              <1> 	;
  2142 00003AB6 50                  <1> 	push	eax ; 01/07/2015
  2143 00003AB7 66B81000            <1> 	mov     ax, KDATA
  2144 00003ABB 8ED8                <1>         mov     ds, ax
  2145 00003ABD 8EC0                <1>         mov     es, ax
  2146 00003ABF 8EE0                <1>         mov     fs, ax
  2147 00003AC1 8EE8                <1>         mov     gs, ax
  2148 00003AC3 A1[A86D0000]        <1> 	mov	eax, [k_page_dir]
  2149 00003AC8 0F22D8              <1> 	mov	cr3, eax
  2150 00003ACB 58                  <1> 	pop	eax ; 01/07/2015
  2151                              <1> 	; 19/10/2015
  2152 00003ACC FC                  <1> 	cld
  2153                              <1> 	;
  2154 00003ACD FE05[9A6E0000]      <1> 	inc	byte [sysflg]
  2155                              <1> 		; incb sysflg / indicate a system routine is in progress
  2156 00003AD3 FB                  <1>         sti 	; 18/01/2014
  2157                              <1> 	;jnz     panic ; 24/05/2013
  2158                              <1> 	; 04/12/2021
  2159 00003AD4 7405                <1> 	jz	short _1
  2160 00003AD6 E969F9FFFF          <1> 	jmp	panic
  2161                              <1> 		; beq 1f
  2162                              <1> 		; jmp panic ; / called if trap inside system
  2163                              <1> ;1:
  2164                              <1> _1:	; 04/12/2021
  2165                              <1> 	; 16/04/2015
  2166 00003ADB A3[A46E0000]        <1> 	mov	[u.r0], eax
  2167 00003AE0 8925[A06E0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2168                              <1> 	;
  2169                              <1> 		; mov $s.syst+2,clockp
  2170                              <1> 		; mov r0,-(sp) / save user registers 
  2171                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2172                              <1> 			   ; / in u.r0
  2173                              <1> 		; mov r1,-(sp)
  2174                              <1> 		; mov r2,-(sp)
  2175                              <1> 		; mov r3,-(sp)
  2176                              <1> 		; mov r4,-(sp)
  2177                              <1> 		; mov r5,-(sp)
  2178                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2179                              <1> 		             ; / arithmetic unit
  2180                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2181                              <1> 		             ; / extended arithmetic unit
  2182                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2183                              <1> 		             ; / arithmetic unit
  2184                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2185                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2186                              <1> 		; mov -(r0),r0 / sys inst in r0 10400xxx
  2187                              <1> 		; sub $sys,r0 / get xxx code
  2188 00003AE6 C1E002              <1> 	shl	eax, 2
  2189                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2190 00003AE9 3DA0000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2191                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2192                              <1> 	;jnb	short badsys
  2193                              <1> 		; bhis badsys / yes, bad system call
  2194                              <1> 	; 25/12/2021
  2195 00003AEE 7205                <1> 	jb	short _2
  2196 00003AF0 E969010000          <1> 	jmp	badsys
  2197                              <1> _2:
  2198                              <1> 	; 25/12/2021
  2199                              <1> 	;cmc
  2200                              <1> 	;pushf	
  2201                              <1> 	;push	eax
  2202 00003AF5 8B2D[9C6E0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2203                              <1> 	;mov	al, 0FEh ; 11111110b
  2204                              <1> 	;;adc	al, 0 ; al = al + cf
  2205                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2206 00003AFB 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2207                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2208                              <1> 				 ; / and clear carry bit
  2209                              <1> 	;pop	ebp ; eax
  2210 00003AFF 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2211                              <1> 	;popf
  2212                              <1>         ;;jc	badsys
  2213                              <1> 	;; 04/12/2021
  2214                              <1> 	;jnc	short _3
  2215                              <1> 	;jmp	badsys
  2216                              <1> ;_3:
  2217 00003B01 A1[A46E0000]        <1> 	mov	eax, [u.r0]
  2218                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2219 00003B06 FFA5[0C3B0000]      <1> 	jmp	dword [ebp+syscalls]
  2220                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2221                              <1> 		            ; / to proper system routine.
  2222                              <1> 
  2223                              <1> 	; 09/01/2022
  2224                              <1> 	; 01/01/2022 (/etc/init error, BugFix efforts, test)
  2225                              <1> syscalls: ; 1:
  2226                              <1> 	; 21/09/2015
  2227                              <1> 	; 01/07/2015
  2228                              <1> 	; 16/04/2015 (32 bit address modification) 
  2229 00003B0C [283C0000]          <1> 	dd sysrele	; / 0
  2230 00003B10 [E33C0000]          <1> 	dd sysexit 	; / 1
  2231 00003B14 [113E0000]          <1> 	dd sysfork 	; / 2
  2232 00003B18 [173F0000]          <1> 	dd sysread 	; / 3
  2233 00003B1C [4B3F0000]          <1> 	dd syswrite 	; / 4
  2234 00003B20 [E73F0000]          <1> 	dd sysopen 	; / 5
  2235 00003B24 [E6400000]          <1> 	dd sysclose 	; / 6
  2236 00003B28 [943D0000]          <1> 	dd syswait 	; / 7
  2237                              <1> 	
  2238                              <1> 	; temporary - 'syscreat, syslink, sysunlink' system calls are disabled
  2239                              <1> 	;	       for 32KB limit test ; 01/01/2022
  2240                              <1> 	;dd syscreat 	; / 8
  2241                              <1> 	;dd syslink 	; / 9
  2242                              <1> 	;dd sysunlink 	; / 10
  2243 00003B2C [5E3C0000]          <1> 	dd badsys
  2244 00003B30 [5E3C0000]          <1> 	dd badsys
  2245 00003B34 [5E3C0000]          <1> 	dd badsys
  2246                              <1> 	
  2247 00003B38 [F9430000]          <1> 	dd sysexec 	; / 11
  2248 00003B3C [4F4A0000]          <1> 	dd syschdir 	; / 12
  2249 00003B40 [734B0000]          <1> 	dd systime 	; / 13
  2250                              <1> 	
  2251                              <1> 	; temporary - 'sysmkdir' is disabled for 32KB limit test ; 01/01/2022
  2252                              <1> 	;dd sysmkdir 	; / 14
  2253 00003B44 [5E3C0000]          <1> 	dd badsys
  2254                              <1> 	
  2255 00003B48 [AA4A0000]          <1> 	dd syschmod 	; / 15
  2256 00003B4C [D94A0000]          <1> 	dd syschown 	; / 16
  2257                              <1> 	
  2258                              <1> 	; temporary - 'sysbreak' is disabled for 32KB limit test ; 01/01/2022
  2259                              <1> 	;dd sysbreak 	; / 17
  2260 00003B50 [5E3C0000]          <1> 	dd badsys
  2261                              <1> 	
  2262 00003B54 [96470000]          <1> 	dd sysstat 	; / 18
  2263 00003B58 [A74B0000]          <1> 	dd sysseek 	; / 19
  2264 00003B5C [B94B0000]          <1> 	dd systell 	; / 20
  2265 00003B60 [8E5A0000]          <1> 	dd sysmount 	; / 21
  2266 00003B64 [405B0000]          <1> 	dd sysumount 	; / 22
  2267 00003B68 [2C4C0000]          <1> 	dd syssetuid 	; / 23
  2268 00003B6C [614C0000]          <1> 	dd sysgetuid 	; / 24
  2269 00003B70 [824B0000]          <1> 	dd sysstime 	; / 25
  2270 00003B74 [204C0000]          <1> 	dd sysquit 	; / 26
  2271 00003B78 [144C0000]          <1> 	dd sysintr 	; / 27
  2272 00003B7C [7C470000]          <1> 	dd sysfstat 	; / 28
  2273 00003B80 [01410000]          <1> 	dd sysemt 	; / 29
  2274 00003B84 [2F410000]          <1> 	dd sysmdate 	; / 30
  2275 00003B88 [7E410000]          <1> 	dd sysstty 	; / 31
  2276 00003B8C [EC420000]          <1> 	dd sysgtty 	; / 32
  2277 00003B90 [2A410000]          <1> 	dd sysilgins 	; / 33
  2278 00003B94 [B9630000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2279                              <1> 			     ; 11/06/2014
  2280 00003B98 [E6630000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2281                              <1> 			     ; 01/07/2015
  2282 00003B9C [BE640000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2283                              <1> 			     ; 21/09/2015 - get last error number
  2284                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  2285                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  2286 00003BA0 [714C0000]          <1> 	dd syssetgid	; 37
  2287 00003BA4 [944C0000]          <1> 	dd sysgetgid	; 38
  2288                              <1> 	; 18/06/2021 - Retro UNIX 386 v2 (ref: TRDOS 386 v2)
  2289 00003BA8 [AC4C0000]          <1> 	dd sysver	; 39 ; (get) Retro Unix 386 version
  2290                              <1> 
  2291                              <1> end_of_syscalls:
  2292                              <1> 
  2293                              <1> error:
  2294                              <1> 	; 11/12/2021 (Retro UNIX 386 v1.2)
  2295                              <1> 	; 17/09/2015
  2296                              <1> 	; 03/09/2015
  2297                              <1> 	; 01/09/2015
  2298                              <1> 	; 09/06/2015
  2299                              <1> 	; 13/05/2015
  2300                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2301                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2302                              <1> 	;
  2303                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2304                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2305                              <1> 	;
  2306                              <1> 	; INPUTS -> none
  2307                              <1> 	; OUTPUTS ->
  2308                              <1> 	;	processor status - carry (c) bit is set (means error)
  2309                              <1> 	;
  2310                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2311                              <1> 	; 	      Because, jumps to error procedure
  2312                              <1> 	;	      disrupts push-pop nesting balance)
  2313                              <1> 	;
  2314 00003BAC 8B2D[9C6E0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2315 00003BB2 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2316                              <1> 				 ; (system call will return with cf = 1)
  2317                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2318                              <1> 		               ; / users stack
  2319                              <1> 	; 17/09/2015
  2320 00003BB6 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2321                              <1> 				 ; for saving/restoring user registers	
  2322                              <1> 	;cmp	ebp, [u.usp]
  2323                              <1> 	;je	short err0	
  2324 00003BB9 892D[A06E0000]      <1> 	mov	[u.usp], ebp
  2325                              <1> ;err0:
  2326                              <1> 	; 01/09/2015
  2327 00003BBF 8B25[A06E0000]      <1> 	mov	esp, [u.usp]	; Retro Unix 8086 v1 modification!
  2328                              <1> 				; 10/04/2013
  2329                              <1> 				; (If an I/O error occurs during disk I/O,
  2330                              <1> 				; related procedures will jump to 'error'
  2331                              <1> 				; procedure directly without returning to 
  2332                              <1> 				; the caller procedure. So, stack pointer
  2333                              <1> 				; must be restored here.)
  2334                              <1> 	; 13/05/2015
  2335                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2336                              <1> 	;	'get last error' system call later. 	
  2337                              <1> 
  2338                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2339 00003BC5 C605[166F0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2340                              <1> 
  2341                              <1> sysret: ; < return from system call>
  2342                              <1> 	; 11/12/2021
  2343                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2344                              <1> 	; 30/11/2021
  2345                              <1> 	; 10/09/2015
  2346                              <1> 	; 29/07/2015
  2347                              <1> 	; 25/06/2015
  2348                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2349                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2350                              <1> 	;
  2351                              <1> 	; 'sysret' first checks to see if process is about to be 
  2352                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2353                              <1> 	; If not, following happens:	 
  2354                              <1> 	; 	1) The user's stack pointer is restored.
  2355                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2356                              <1> 	;	   i-node has been modified. If it has, it is written out
  2357                              <1> 	;	   via 'ppoke'.
  2358                              <1> 	;	3) If the super block has been modified, it is written out
  2359                              <1> 	;	   via 'ppoke'.				
  2360                              <1> 	;	4) If the dismountable file system's super block has been
  2361                              <1> 	;	   modified, it is written out to the specified device
  2362                              <1> 	;	   via 'ppoke'.
  2363                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2364                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2365                              <1> 	;	   another user a chance to run.
  2366                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2367                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2368                              <1> 	;
  2369                              <1> 	; Calling sequence:
  2370                              <1> 	;	jump table or 'br sysret'
  2371                              <1> 	; Arguments: 
  2372                              <1> 	;	-	
  2373                              <1> 	; ...............................................................
  2374                              <1> 	;	
  2375                              <1> 	; ((AX=r1 for 'iget' input))
  2376                              <1> 	;	
  2377                              <1> 	;xor	ax, ax ; 04/05/2013
  2378                              <1> 	; 30/11/2021
  2379 00003BCC 31C0                <1> 	xor	eax, eax
  2380                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2381 00003BCE FEC0                <1> 	inc	al ; 04/05/2013
  2382 00003BD0 3805[F46E0000]      <1> 	cmp	[u.bsys], al ; 1
  2383                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2384                              <1> 	;jnb	sysexit ; 04/05/2013
  2385                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2386                              <1> 	; 04/12/2021
  2387 00003BD6 720F                <1> 	jb	short _3
  2388                              <1> 	; 11/12/2021
  2389 00003BD8 C705[186F0000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2389 00003BE0 0000                <1>
  2390 00003BE2 E9FC000000          <1> 	jmp	sysexit
  2391                              <1> _3:
  2392                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2393                              <1> 		; mov u.sp,sp / no point stack to users stack
  2394 00003BE7 FEC8                <1> 	dec 	al ; mov ax, 0
  2395                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2396 00003BE9 E882160000          <1> 	call	iget
  2397                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2398                              <1> 		            ; / it is written out
  2399                              <1> 	;xor 	ax, ax ; 0
  2400                              <1> 	; 30/11/2021
  2401 00003BEE 31C0                <1> 	xor	eax, eax
  2402 00003BF0 3805[986E0000]      <1> 	cmp	[smod], al ; 0
  2403                              <1> 		; tstb	smod / has the super block been modified
  2404 00003BF6 7614                <1> 	jna	short sysret1
  2405                              <1> 		; beq	1f / no, 1f
  2406 00003BF8 A2[986E0000]        <1> 	mov	[smod], al ; 0
  2407                              <1> 		; clrb smod / yes, clear smod
  2408 00003BFD BB[4C6F0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2409 00003C02 66810B0002          <1>    	or	word [ebx], 200h ;;
  2410                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2411                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2412                              <1> 		      	      ; / output
  2413                              <1> 	; AX = 0
  2414 00003C07 E8B3230000          <1> 	call 	poke ; 07/08/2013
  2415                              <1> 	;call	ppoke
  2416                              <1> 	; AX = 0
  2417                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2418                              <1> sysret1: ;1:
  2419 00003C0C 3805[996E0000]      <1> 	cmp	[mmod], al ; 0
  2420                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2421                              <1> 		           ; / system
  2422 00003C12 7614                <1> 	jna	short sysrel0
  2423                              <1> 		; beq 1f / been modified?  no, 1f
  2424 00003C14 A2[996E0000]        <1> 	mov	[mmod], al ; 0	
  2425                              <1> 		; clrb	mmod / yes, clear mmod
  2426                              <1>         ;mov    ax, [mntd]
  2427                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2428 00003C19 BB[54710000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2429                              <1>         ;;mov	[ebx], al
  2430                              <1> 	;mov    [sb1], al
  2431                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2432 00003C1E 66810B0002          <1> 	or	word [ebx], 200h
  2433                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2434                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2435 00003C23 E897230000          <1> 	call	poke ; 07/08/2013
  2436                              <1> 	;call	ppoke 
  2437                              <1> 		; jsr r0,ppoke / write it out to its device
  2438                              <1>         ;xor    al, al ; 26/04/2013       
  2439                              <1> ;1:
  2440                              <1> 		; tstb uquant / is the time quantum 0?
  2441                              <1> 		; bne 1f / no, don't swap it out
  2442                              <1> 
  2443                              <1> sysrele: ; < release >
  2444                              <1> 	; 14/10/2015
  2445                              <1> 	; 01/09/2015
  2446                              <1> 	; 24/07/2015
  2447                              <1> 	; 14/05/2015
  2448                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2449                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2450                              <1> 	;
  2451                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2452                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2453                              <1> 	; turns off the system flag. It then checked to see if there is
  2454                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2455                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2456                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2457                              <1> 	; the user, a rti is made.
  2458                              <1> 	;
  2459                              <1> 	; Calling sequence:
  2460                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2461                              <1> 	; Arguments:
  2462                              <1> 	;	-	
  2463                              <1> 	; ...............................................................
  2464                              <1> 	;	
  2465                              <1> 	; 23/02/2014 (swapret)
  2466                              <1> 	; 22/09/2013
  2467                              <1> sysrel0: ;1:
  2468 00003C28 803D[EC6E0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2469                              <1> 		; tstb uquant / is the time quantum 0?
  2470 00003C2F 7705                <1>         ja      short swapret
  2471                              <1> 		; bne 1f / no, don't swap it out
  2472                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2473 00003C31 E8BD100000          <1> 	call	tswap
  2474                              <1> 		; jsr r0,tswap / yes, swap it out
  2475                              <1> ;
  2476                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2477                              <1> swapret: ;1:
  2478                              <1> 	; 10/09/2015
  2479                              <1> 	; 01/09/2015
  2480                              <1> 	; 14/05/2015
  2481                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2482                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2483                              <1> 	; cli
  2484                              <1> 	; 24/07/2015
  2485                              <1> 	;
  2486                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2487                              <1> 	;; mov	esp, [u.usp]
  2488                              <1> 
  2489                              <1> 	; 22/09/2013
  2490 00003C36 E89D120000          <1> 	call	isintr
  2491                              <1> 	; 20/10/2013
  2492 00003C3B 7405                <1> 	jz	short sysrel1
  2493 00003C3D E88A000000          <1> 	call	intract
  2494                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2495                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2496                              <1> 		               ; / action
  2497                              <1> sysrel1:
  2498 00003C42 FA                  <1> 	cli ; 14/10/2015
  2499 00003C43 FE0D[9A6E0000]      <1> 	dec	byte [sysflg]
  2500                              <1> 		; decb sysflg / turn system flag off
  2501 00003C49 A1[046F0000]        <1> 	mov     eax, [u.pgdir]
  2502 00003C4E 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2503                              <1> 			  ; (others are different than kernel page tables) 
  2504                              <1> 	; 10/09/2015
  2505 00003C51 61                  <1> 	popad ; edi, esi, ebp, temp (increment esp by 4), ebx, edx, ecx, eax
  2506                              <1> 		; mov (sp)+,sc / restore user registers
  2507                              <1> 		; mov (sp)+,mq
  2508                              <1> 		; mov (sp)+,ac
  2509                              <1> 		; mov (sp)+,r5
  2510                              <1> 		; mov (sp)+,r4
  2511                              <1> 		; mov (sp)+,r3
  2512                              <1> 		; mov (sp)+,r2
  2513                              <1> 	;
  2514 00003C52 A1[A46E0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2515 00003C57 0FA9                <1> 	pop	gs
  2516 00003C59 0FA1                <1> 	pop	fs
  2517 00003C5B 07                  <1> 	pop	es
  2518 00003C5C 1F                  <1> 	pop	ds
  2519 00003C5D CF                  <1> 	iretd	
  2520                              <1> 		; rti / no, return from interrupt
  2521                              <1> 
  2522                              <1> badsys:
  2523                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2524                              <1> 	; (Major Modification: 'core' dumping procedure in
  2525                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2526                              <1> 	;	has been changed to print 'Invalid System Call !'
  2527                              <1> 	;	message on the user's console tty.)
  2528                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2529                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2530                              <1> 	; (EAX = Function number)  
  2531                              <1> 	;
  2532 00003C5E FE05[F46E0000]      <1> 	inc	byte [u.bsys]
  2533                              <1> 	;
  2534 00003C64 8B1D[9C6E0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2535 00003C6A 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2536 00003C6C E839DBFFFF          <1> 	call	dwordtohex
  2537 00003C71 8915[046B0000]      <1> 	mov	[bsys_msg_eip], edx
  2538 00003C77 A3[086B0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2539 00003C7C A1[A46E0000]        <1> 	mov	eax, [u.r0]
  2540 00003C81 E824DBFFFF          <1> 	call	dwordtohex
  2541 00003C86 8915[F46A0000]      <1> 	mov	[bsys_msg_eax], edx
  2542 00003C8C A3[F86A0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2543                              <1> 	; 11/12/2021
  2544                              <1> 	;xor	eax, eax
  2545                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2546                              <1> 	;mov	ebx, [u.fofp]
  2547                              <1> 	;mov	[ebx], eax
  2548                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2549                              <1> 	;inc	eax
  2550                              <1> 	; 11/12/2021 - Retro UNIX 386 v2 fs compatibility 
  2551                              <1> 	; (Retro UNIX 386 v1.2)
  2552                              <1> 	;mov	al, 8 ; /dev/tty inode number (runix v2 fs)
  2553                              <1> 	;; eax = 8 ; inode number of console tty (for user)	
  2554                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2555                              <1> 		; writei
  2556                              <1> 		; INPUTS ->
  2557                              <1> 		;    r1 - inode number
  2558                              <1> 		;    u.count - byte count to be written
  2559                              <1> 		;    u.base - points to user buffer
  2560                              <1> 		;    u.fofp - points to word with current file offset
  2561                              <1> 		; OUTPUTS ->
  2562                              <1> 		;    u.count - cleared
  2563                              <1> 		;    u.nread - accumulates total bytes passed back	
  2564                              <1> 		;
  2565                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2566                              <1> 	;call	writei
  2567                              <1> 	;;mov	eax, 1
  2568                              <1> 	;jmp	sysexit
  2569                              <1> 
  2570                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2571 00003C91 BE[D56A0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2572 00003C96 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2573                              <1> ; temporary - 12/12/2021
  2574                              <1> ;mov bl, 1
  2575 00003C9D 8A83[DF6B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2576                              <1> ;mov al, 0
  2577 00003CA3 C605[D76D0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2578 00003CAA A2[D96E0000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2579 00003CAF E8EF270000          <1> 	call	print_cmsg
  2580                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2581                              <1> 
  2582                              <1> ; temporary - 11/12/2021
  2583 00003CB4 C70500800B00324E32- <1> mov dword [0B8000h], 4E324E32h
  2583 00003CBD 4E                  <1>
  2584 00003CBE B9FFFF0000          <1> mov ecx, 0FFFFh
  2585                              <1> abovexfx:
  2586 00003CC3 4A                  <1> dec edx
  2587 00003CC4 42                  <1> inc edx
  2588 00003CC5 E2FC                <1> loop abovexfx
  2589                              <1> 
  2590 00003CC7 E9E0FEFFFF          <1> 	jmp	error
  2591                              <1> 
  2592                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2593                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2594                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2595                              <1> 		; br 1f / error
  2596                              <1> 		; neg r1 / negate the i-number to open the core image file
  2597                              <1> 		       ; / for writing
  2598                              <1> 		; jsr r0,iopen / open the core image file
  2599                              <1> 		; jsr r0,itrunc / free all associated blocks
  2600                              <1> 		; br 2f
  2601                              <1> ;1:
  2602                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2603                              <1> 		; jsr r0,maknod / make an i-node
  2604                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2605                              <1> ;2:
  2606                              <1> 		; mov $core,u.base / move address core to u.base
  2607                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2608                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2609                              <1> 		; clr u.off / clear user offset
  2610                              <1> 		; jsr r0,writei / write out the core image to the user
  2611                              <1> 		; mov $user,u.base / pt. u.base to user
  2612                              <1> 		; mov $64.,u.count / u.count = 64
  2613                              <1> 		; jsr r0,writei / write out all the user parameters
  2614                              <1> 		; neg r1 / make i-number positive
  2615                              <1> 		; jsr r0,iclose / close the core image file
  2616                              <1> 		; br sysexit /
  2617                              <1> ;3:
  2618                              <1> 		; <core\0\0>
  2619                              <1> 
  2620                              <1> intract: ; / interrupt action
  2621                              <1> 	; 14/10/2015
  2622                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2623                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2624                              <1> 	;
  2625                              <1> 	; Retro UNIX 8086 v1 modification !
  2626                              <1> 	; (Process/task switching and quit routine by using
  2627                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2628                              <1> 	;
  2629                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2630                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2631                              <1> 	;		'intract' will jump to 'sysexit'.
  2632                              <1> 	;	    Intract will return to the caller 
  2633                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2634                              <1> 	; 14/10/2015
  2635 00003CCC FB                  <1> 	sti
  2636                              <1> 	; 07/12/2013	
  2637 00003CCD 66FF05[F26E0000]    <1> 	inc 	word [u.quit]
  2638 00003CD4 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2639 00003CD6 66FF0D[F26E0000]    <1> 	dec	word [u.quit]
  2640                              <1> 	; 16/04/2015
  2641 00003CDD C3                  <1> 	retn
  2642                              <1> intrct0:	
  2643 00003CDE 58                  <1> 	pop	eax ; call intract -> retn
  2644                              <1> 	;
  2645 00003CDF 31C0                <1> 	xor 	eax, eax
  2646 00003CE1 FEC0                <1> 	inc	al  ; mov ax, 1
  2647                              <1> ;;;
  2648                              <1> 	; UNIX v1 original 'intract' routine... 
  2649                              <1> 	; / interrupt action
  2650                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2651                              <1> 		; bne 1f / no, 1f
  2652                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2653                              <1> 	; 1: / now in user area
  2654                              <1> 		; mov r1,-(sp) / save r1
  2655                              <1> 		; mov u.ttyp,r1 
  2656                              <1> 			; / pointer to tty buffer in control-to r1
  2657                              <1> 		; cmpb 6(r1),$177
  2658                              <1> 			; / is the interrupt char equal to "del"
  2659                              <1> 		; beq 1f / yes, 1f
  2660                              <1> 		; clrb 6(r1) 
  2661                              <1> 		        ; / no, clear the byte 
  2662                              <1> 			; / (must be a quit character)
  2663                              <1> 		; mov (sp)+,r1 / restore r1
  2664                              <1> 		; clr u.quit / clear quit flag
  2665                              <1> 		; bis $20,2(sp) 
  2666                              <1> 		    	; / set trace for quit (sets t bit of 
  2667                              <1> 			; / ps-trace trap)
  2668                              <1> 		; rti   ;  / return from interrupt
  2669                              <1> 	; 1: / interrupt char = del
  2670                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2671                              <1> 			   ; / in the buffer
  2672                              <1> 		; mov (sp)+,r1 / restore r1
  2673                              <1> 		; cmp u.intr,$core / should control be 
  2674                              <1> 				; / transferred to loc core?
  2675                              <1> 		; blo 1f
  2676                              <1> 		; jmp *u.intr / user to do rti yes, 
  2677                              <1> 				; / transfer to loc core
  2678                              <1> 	; 1:
  2679                              <1> 		; sys 1 / exit
  2680                              <1> 
  2681                              <1> sysexit: ; <terminate process>
  2682                              <1> 	; 30/11/2021 - etro UNIX 386 v1.2
  2683                              <1> 	; 01/09/2015
  2684                              <1> 	; 31/08/2015
  2685                              <1> 	; 14/05/2015
  2686                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2687                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2688                              <1> 	;
  2689                              <1> 	; 'sysexit' terminates a process. First each file that
  2690                              <1> 	; the process has opened is closed by 'flose'. The process
  2691                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2692                              <1> 	; searched to find children of the dying process. If any of
  2693                              <1> 	; children are zombies (died by not waited for), they are
  2694                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2695                              <1> 	; dying process's parent. When the parent is found, it is
  2696                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2697                              <1> 	; one of these, the dying process just dies. If it is waiting
  2698                              <1> 	; for a child process to die, it notified that it doesn't 
  2699                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2700                              <1> 	; (waiting to active). It is awakened and put on runq by
  2701                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2702                              <1> 	; it will never be run again but stays around until a 'wait'
  2703                              <1> 	; is completed by it's parent process. If the parent is not
  2704                              <1> 	; found, process just dies. This means 'swap' is called with
  2705                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2706                              <1> 	; to write out the process and 'rswap' reads the new process
  2707                              <1> 	; over the one that dies..i.e., the dying process is 
  2708                              <1> 	; overwritten and destroyed.	
  2709                              <1>  	;
  2710                              <1> 	; Calling sequence:
  2711                              <1> 	;	sysexit or conditional branch.
  2712                              <1> 	; Arguments:
  2713                              <1> 	;	-	
  2714                              <1> 	; ...............................................................
  2715                              <1> 	;	
  2716                              <1> 	; Retro UNIX 8086 v1 modification: 
  2717                              <1> 	;       System call number (=1) is in EAX register.
  2718                              <1> 	;
  2719                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2720                              <1> 	;       registers depending of function details.
  2721                              <1> 	;
  2722                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2723                              <1> 	;
  2724                              <1> ; / terminate process
  2725                              <1> 	; AX = 1
  2726                              <1> 	;dec 	ax ; 0
  2727                              <1> 	; 30/11/2021
  2728 00003CE3 48                  <1> 	dec	eax ; 0
  2729 00003CE4 66A3[F06E0000]      <1> 	mov	[u.intr], ax ; 0
  2730                              <1> 		; clr u.intr / clear interrupt control word
  2731                              <1> 		; clr r1 / clear r1
  2732                              <1> 
  2733                              <1> ; temporary - 26/12/2021
  2734 00003CEA B9FFFF0000          <1> mov ecx, 0FFFFh
  2735                              <1> fcloop:
  2736 00003CEF 48                  <1> dec	eax
  2737 00003CF0 40                  <1> inc	eax
  2738 00003CF1 4A                  <1> dec	edx
  2739 00003CF2 42                  <1> inc	edx
  2740 00003CF3 E2FA                <1> loop	fcloop
  2741                              <1> 
  2742                              <1> 	; AX = 0
  2743                              <1> sysexit_1: ; 1:
  2744                              <1> 	; AX = File descriptor
  2745                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2746                              <1> 		; / Search the whole list
  2747 00003CF5 E82F0B0000          <1> 	call	fclose
  2748                              <1> 		; jsr r0,fclose / close all files the process opened
  2749                              <1> 	;; ignore error return
  2750                              <1> 		; br .+2 / ignore error return
  2751                              <1> 	;inc	ax
  2752 00003CFA FEC0                <1> 	inc	al
  2753                              <1> 		; inc r1 / increment file descriptor
  2754                              <1> 	;cmp	ax, 10
  2755 00003CFC 3C0A                <1> 	cmp	al, 10
  2756                              <1> 		; cmp r1,$10. / end of u.fp list?
  2757 00003CFE 72F5                <1> 	jb	short sysexit_1
  2758                              <1> 		; blt 1b / no, go back
  2759 00003D00 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2760                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2761 00003D07 88A3[0F6C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2762                              <1> 		; clrb p.stat-1(r1) / free the process
  2763                              <1> 	;shl	bx, 1
  2764 00003D0D D0E3                <1> 	shl	bl, 1
  2765                              <1> 		; asl r1 / use r1 for index into the below tables
  2766 00003D0F 668B8B[7E6B0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2767                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2768 00003D16 668B93[9E6B0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2769                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2770                              <1> 	; xor 	bx, bx ; 0
  2771 00003D1D 30DB                <1> 	xor	bl, bl ; 0
  2772                              <1> 		; clr r2
  2773 00003D1F 31F6                <1> 	xor	esi, esi ; 0
  2774                              <1> 		; clr r5 / initialize reg
  2775                              <1> sysexit_2: ; 1:
  2776                              <1> 	        ; / find children of this dying process, 
  2777                              <1> 		; / if they are zombies, free them
  2778                              <1> 	;add	bx, 2
  2779 00003D21 80C302              <1> 	add	bl, 2
  2780                              <1> 		; add $2,r2 / search parent process table 
  2781                              <1> 		          ; / for dying process's name
  2782 00003D24 66398B[9E6B0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2783                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2784 00003D2B 7513                <1> 	jne	short sysexit_4
  2785                              <1> 		; bne 3f / no
  2786                              <1> 	;shr	bx, 1
  2787 00003D2D D0EB                <1> 	shr	bl, 1
  2788                              <1> 		; asr r2 / yes, it is a parent
  2789 00003D2F 80BB[0F6C0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2790                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2791                              <1> 				     ; / dying process a zombie
  2792 00003D36 7506                <1> 	jne	short sysexit_3 
  2793                              <1> 		; bne 2f / no
  2794 00003D38 88A3[0F6C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2795                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2796                              <1> sysexit_3: ; 2:
  2797                              <1> 	;shr	bx, 1
  2798 00003D3E D0E3                <1> 	shl	bl, 1
  2799                              <1> 		; asl r2
  2800                              <1> sysexit_4: ; 3:
  2801                              <1> 		; / search the process name table 
  2802                              <1> 		; / for the dying process's parent
  2803 00003D40 663993[7E6B0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2804                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2805 00003D47 7502                <1> 	jne	short sysexit_5
  2806                              <1> 		; bne 3f / no
  2807 00003D49 89DE                <1> 	mov	esi, ebx
  2808                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2809                              <1> 		          ; / process # x2) in r5
  2810                              <1> sysexit_5: ; 3:
  2811                              <1> 	;cmp	bx, nproc + nproc
  2812 00003D4B 80FB20              <1> 	cmp	bl, nproc + nproc
  2813                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2814 00003D4E 72D1                <1> 	jb	short sysexit_2
  2815                              <1> 		; blt 1b / no, go back
  2816                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2817 00003D50 21F6                <1> 	and	esi, esi ; r5=r1
  2818 00003D52 7431                <1> 	jz	short sysexit_6
  2819                              <1> 		; beq 2f / no parent has been found. 
  2820                              <1> 		       ; / The process just dies
  2821 00003D54 66D1EE              <1> 	shr	si, 1
  2822                              <1> 		; asr r1 / set up index to p.stat
  2823 00003D57 8A86[0F6C0000]      <1> 	mov	al, [esi+p.stat-1]
  2824                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2825 00003D5D 20C0                <1> 	and	al, al
  2826 00003D5F 7424                <1> 	jz	short sysexit_6
  2827                              <1> 		; beq 2f / if its been freed, 2f
  2828 00003D61 3C03                <1> 	cmp	al, 3
  2829                              <1> 		; cmp r2,$3 / is parent a zombie?
  2830 00003D63 7420                <1> 	je	short sysexit_6
  2831                              <1> 		; beq 2f / yes, 2f
  2832                              <1> 	; BH = 0
  2833 00003D65 8A1D[F56E0000]      <1> 	mov	bl, [u.uno]
  2834                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2835 00003D6B C683[0F6C0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2836                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2837                              <1> 	; 05/02/2014
  2838 00003D72 3C01                <1> 	cmp	al, 1 ; SRUN
  2839 00003D74 740F                <1> 	je	short sysexit_6
  2840                              <1> 	;cmp	al, 2
  2841                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2842                              <1> 			  ; / this child to die
  2843                              <1> 	;jne	short sysexit_6	
  2844                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2845                              <1> 	; 05/02/2014
  2846                              <1> 	; p.stat = 2 --> waiting
  2847                              <1> 	; p.stat = 4 --> sleeping
  2848 00003D76 C686[0F6C0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2849                              <1> 	;dec	byte [esi+p.stat-1]
  2850                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2851 00003D7D 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2852                              <1> 	; 
  2853                              <1> 	;mov	ebx, runq + 4
  2854                              <1> 		; mov $runq+4,r2 / on the runq
  2855 00003D80 E845100000          <1> 	call	putlu
  2856                              <1> 		; jsr r0, putlu
  2857                              <1> sysexit_6: ; 2:
  2858                              <1> 	; 31/08/2015
  2859                              <1> 		; / the process dies
  2860 00003D85 C605[F56E0000]00    <1> 	mov	byte [u.uno], 0
  2861                              <1> 		; clrb u.uno / put zero as the process number, 
  2862                              <1> 	           ; / so "swap" will
  2863 00003D8C E86C0F0000          <1> 	call	swap
  2864                              <1> 		; jsr r0,swap / overwrite process with another process
  2865                              <1> hlt_sys:
  2866                              <1> 	;sti ; 18/01/2014
  2867                              <1> hlts0:
  2868 00003D91 F4                  <1> 	hlt
  2869 00003D92 EBFD                <1> 	jmp	short hlts0
  2870                              <1> 		; 0 / and thereby kill it; halt?
  2871                              <1> 
  2872                              <1> 
  2873                              <1> syswait: ; < wait for a processs to die >
  2874                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  2875                              <1> 	; 17/09/2015
  2876                              <1> 	; 02/09/2015
  2877                              <1> 	; 01/09/2015
  2878                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2879                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2880                              <1> 	;
  2881                              <1> 	; 'syswait' waits for a process die. 
  2882                              <1> 	; It works in following way:
  2883                              <1> 	;    1) From the parent process number, the parent's 
  2884                              <1> 	; 	process name is found. The p.ppid table of parent
  2885                              <1> 	;	names is then searched for this process name.
  2886                              <1> 	;	If a match occurs, r2 contains child's process
  2887                              <1> 	;	number. The child status is checked to see if it is
  2888                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2889                              <1> 	;	If it is, the child process is freed and it's name
  2890                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2891                              <1> 	;	If the child is not a zombie, nothing happens and
  2892                              <1> 	;	the search goes on through the p.ppid table until
  2893                              <1> 	;	all processes are checked or a zombie is found.
  2894                              <1> 	;    2) If no zombies are found, a check is made to see if
  2895                              <1> 	;	there are any children at all. If there are none,
  2896                              <1> 	;	an error return is made. If there are, the parent's
  2897                              <1> 	;	status is set to 2 (waiting for child to die),
  2898                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2899                              <1> 	;	is made to wait on the next process.
  2900                              <1> 	;
  2901                              <1> 	; Calling sequence:
  2902                              <1> 	;	?
  2903                              <1> 	; Arguments:
  2904                              <1> 	;	-
  2905                              <1> 	; Inputs: - 
  2906                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2907                              <1> 	; ...............................................................
  2908                              <1> 	;				
  2909                              <1> 	
  2910                              <1> ; / wait for a process to die
  2911                              <1> 
  2912                              <1> syswait_0:
  2913 00003D94 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2914                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2915 00003D9B D0E3                <1> 	shl	bl, 1
  2916                              <1> 	;shl	bx, 1
  2917                              <1> 		; asl r1 / x2 to get index into p.pid table
  2918 00003D9D 668B83[7E6B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2919                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2920 00003DA4 31F6                <1> 	xor	esi, esi
  2921                              <1> 		; clr r2
  2922 00003DA6 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2923                              <1> 	;xor 	cl, cl
  2924                              <1> 		; clr r3 / initialize reg 3
  2925                              <1> syswait_1: ; 1:
  2926 00003DA8 6683C602            <1> 	add	si, 2
  2927                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2928                              <1> 			  ; / search table of parent processes 
  2929                              <1> 			  ; / for this process name
  2930 00003DAC 663B86[9E6B0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2931                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2932                              <1> 			            ; / process number
  2933 00003DB3 7534                <1> 	jne	short syswait_3
  2934                              <1> 		;bne 3f / branch if no match of parent process name
  2935                              <1> 	;inc	cx
  2936 00003DB5 FEC1                <1> 	inc	cl
  2937                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2938 00003DB7 66D1EE              <1> 	shr	si, 1
  2939                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2940                              <1> 	; The possible states ('p.stat' values) of a process are:
  2941                              <1> 	;	0 = free or unused
  2942                              <1> 	;	1 = active
  2943                              <1> 	;	2 = waiting for a child process to die
  2944                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2945 00003DBA 80BE[0F6C0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2946                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2947 00003DC1 7523                <1> 	jne	short syswait_2
  2948                              <1> 		; bne 2f / no, skip it
  2949 00003DC3 88BE[0F6C0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2950                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2951 00003DC9 66D1E6              <1> 	shl	si, 1
  2952                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2953 00003DCC 0FB786[7E6B0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2954 00003DD3 A3[A46E0000]        <1> 	mov	[u.r0], eax
  2955                              <1> 		; mov p.pid-2(r2),*u.r0 
  2956                              <1> 			      ; / put childs process name in (u.r0)
  2957                              <1> 	;
  2958                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2959                              <1> 	;
  2960                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2961                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2962                              <1> 	; system call loop from the application/program if it calls
  2963                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2964                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2965                              <1> 	;
  2966                              <1> 	; Note: syswait will return with error if there is not a
  2967                              <1> 	;       zombie or running process to wait.	
  2968                              <1> 	;
  2969                              <1> 	;sub	ax, ax
  2970                              <1> 	; 08/01/2022
  2971 00003DD8 29C0                <1> 	sub	eax, eax
  2972 00003DDA 668986[9E6B0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2973 00003DE1 E9E8FDFFFF          <1> 	jmp	sysret0 ; ax = 0
  2974                              <1> 	;
  2975                              <1> 	;jmp	sysret
  2976                              <1> 		; br sysret1 / return cause child is dead
  2977                              <1> syswait_2: ; 2:
  2978 00003DE6 66D1E6              <1> 	shl	si, 1
  2979                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2980                              <1> syswait_3: ; 3:
  2981 00003DE9 6683FE20            <1> 	cmp	si, nproc+nproc
  2982                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2983 00003DED 72B9                <1> 	jb	short syswait_1
  2984                              <1> 		; blt 1b / no, continue search
  2985                              <1> 	;and	cx, cx
  2986 00003DEF 20C9                <1> 	and	cl, cl
  2987                              <1> 		; tst r3 / one gets here if there are no children 
  2988                              <1> 		       ; / or children that are still active
  2989                              <1> 	; 30/10/2013
  2990 00003DF1 750B                <1> 	jnz	short syswait_4
  2991                              <1> 	;jz	error
  2992                              <1> 		; beq error1 / there are no children, error
  2993 00003DF3 890D[A46E0000]      <1> 	mov	[u.r0], ecx ; 0
  2994 00003DF9 E9AEFDFFFF          <1> 	jmp	error
  2995                              <1> syswait_4:
  2996 00003DFE 8A1D[F56E0000]      <1> 	mov	bl, [u.uno]
  2997                              <1> 		; movb u.uno,r1 / there are children so put 
  2998                              <1> 			      ; / parent process number in r1
  2999 00003E04 FE83[0F6C0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  3000                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  3001                              <1> 				  ; / other children to die
  3002                              <1> 	; 04/11/2013
  3003 00003E0A E8EE0E0000          <1> 	call	swap
  3004                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  3005 00003E0F EB83                <1> 	jmp	syswait_0
  3006                              <1> 		; br syswait / wait on next process
  3007                              <1> 
  3008                              <1> sysfork: ; < create a new process >
  3009                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  3010                              <1> 	; 18/09/2015
  3011                              <1> 	; 04/09/2015
  3012                              <1> 	; 02/09/2015
  3013                              <1> 	; 01/09/2015
  3014                              <1> 	; 28/08/2015
  3015                              <1> 	; 14/05/2015
  3016                              <1> 	; 10/05/2015
  3017                              <1> 	; 09/05/2015
  3018                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3019                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3020                              <1> 	;
  3021                              <1> 	; 'sysfork' creates a new process. This process is referred
  3022                              <1> 	; to as the child process. This new process core image is
  3023                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3024                              <1> 	; distinction is the return location and the fact that (u.r0)
  3025                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3026                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3027                              <1> 	; 'sysfork' works in the following manner: 	
  3028                              <1> 	;    1) The process status table (p.stat) is searched to find
  3029                              <1> 	;	a process number that is unused. If none are found
  3030                              <1> 	;	an error occurs.
  3031                              <1> 	;    2) when one is found, it becomes the child process number
  3032                              <1> 	;	and it's status (p.stat) is set to active.
  3033                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3034                              <1> 	;	character in that tty buffer is cleared.
  3035                              <1> 	;    4) The child process is put on the lowest priority run 
  3036                              <1> 	;	queue via 'putlu'.
  3037                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3038                              <1> 	;	it is a unique number) and is put in the child's unique
  3039                              <1> 	;	identifier; process id (p.pid).
  3040                              <1> 	;    6) The process name of the parent is then obtained and
  3041                              <1> 	;	placed in the unique identifier of the parent process
  3042                              <1> 	;	name is then put in 'u.r0'.	
  3043                              <1> 	;    7) The child process is then written out on disk by
  3044                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3045                              <1> 	;	and the child is born. (The child process is written 
  3046                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3047                              <1> 	;	number.)
  3048                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3049                              <1> 	;    9) The child process name is put in 'u.r0'.
  3050                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3051                              <1> 	;	create the return address for the parent process.
  3052                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3053                              <1> 	;	the parent has opened. For each file the parent has
  3054                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3055                              <1> 	;	to indicate that the child process also has opened
  3056                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3057                              <1> 	;
  3058                              <1> 	; Calling sequence:
  3059                              <1> 	;	from shell ?
  3060                              <1> 	; Arguments:
  3061                              <1> 	;	-
  3062                              <1> 	; Inputs: -
  3063                              <1> 	; Outputs: *u.r0 - child process name
  3064                              <1> 	; ...............................................................
  3065                              <1> 	;	
  3066                              <1> 	; Retro UNIX 8086 v1 modification: 
  3067                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3068                              <1> 	;	= process id of child a parent process returns
  3069                              <1> 	;	= process id of parent when a child process returns
  3070                              <1> 	;
  3071                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3072                              <1> 	;	in following manner: (with an example: c library, fork)
  3073                              <1> 	;	
  3074                              <1> 	;	1:
  3075                              <1> 	;		sys	fork
  3076                              <1> 	;			br 1f  / child process returns here
  3077                              <1> 	;		bes	2f     / parent process returns here
  3078                              <1> 	;		/ pid of new process in r0
  3079                              <1> 	;		rts	pc
  3080                              <1> 	;	2: / parent process condionally branches here
  3081                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3082                              <1> 	;		rts	pc
  3083                              <1> 	;
  3084                              <1> 	;	1: / child process brances here
  3085                              <1> 	;		clr	r0   / pid = 0 in child process
  3086                              <1> 	;		rts	pc
  3087                              <1> 	;
  3088                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3089                              <1> 	;		// pid = fork();
  3090                              <1> 	;		//
  3091                              <1> 	;		// pid == 0 in child process; 
  3092                              <1> 	;		// pid == -1 means error return
  3093                              <1> 	;		// in child, 
  3094                              <1> 	;		//	parents id is in par_uid if needed
  3095                              <1> 	;		
  3096                              <1> 	;		_fork:
  3097                              <1> 	;			mov	$.fork,eax
  3098                              <1> 	;			int	$0x30
  3099                              <1> 	;			jmp	1f
  3100                              <1> 	;			jnc	2f
  3101                              <1> 	;			jmp	cerror
  3102                              <1> 	;		1:
  3103                              <1> 	;			mov	eax,_par_uid
  3104                              <1> 	;			xor	eax,eax
  3105                              <1> 	;		2:
  3106                              <1> 	;			ret
  3107                              <1> 	;
  3108                              <1> 	;	In Retro UNIX 8086 v1,
  3109                              <1> 	;	'sysfork' returns in following manner:
  3110                              <1> 	;	
  3111                              <1> 	;		mov	ax, sys_fork
  3112                              <1> 	;		mov	bx, offset @f ; routine for child
  3113                              <1> 	;		int	20h
  3114                              <1> 	;		jc	error
  3115                              <1> 	;		
  3116                              <1> 	;	; Routine for parent process here (just after 'jc')
  3117                              <1> 	;		mov	word ptr [pid_of_child], ax
  3118                              <1> 	;		jmp	next_routine_for_parent	
  3119                              <1> 	;
  3120                              <1> 	;	@@: ; routine for child process here				
  3121                              <1> 	;		....	
  3122                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3123                              <1> 	;	       for child process by using BX input.
  3124                              <1> 	;	      (at first, parent process will return then 
  3125                              <1> 	;	      child process will return -after swapped in-
  3126                              <1> 	;	      'syswait' is needed in parent process
  3127                              <1> 	;	      if return from child process will be waited for.)
  3128                              <1> 	;	  				
  3129                              <1> 	
  3130                              <1> ; / create a new process
  3131                              <1> 	; EBX = return address for child process 
  3132                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3133 00003E11 31F6                <1> 	xor 	esi, esi
  3134                              <1> 		; clr r1
  3135                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3136 00003E13 46                  <1> 	inc	esi
  3137                              <1> 		; inc r1
  3138 00003E14 80BE[0F6C0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3139                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3140 00003E1B 760B                <1> 	jna	short sysfork_2	
  3141                              <1> 		; beq 1f / it's unused so branch
  3142 00003E1D 6683FE10            <1> 	cmp	si, nproc
  3143                              <1> 		; cmp r1,$nproc / all processes checked
  3144 00003E21 72F0                <1> 	jb	short sysfork_1
  3145                              <1> 		; blt 1b / no, branch back
  3146                              <1> 	;
  3147                              <1> 	; Retro UNIX 8086 v1. modification:
  3148                              <1> 	;	Parent process returns from 'sysfork' to address 
  3149                              <1> 	;	which is just after 'sysfork' system call in parent
  3150                              <1> 	;	process. Child process returns to address which is put
  3151                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3152                              <1> 	;
  3153                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3154                              <1> 		             ; / to old process return
  3155                              <1> 		; br error1 / no room for a new process
  3156                              <1> sysfork_0:
  3157 00003E23 E984FDFFFF          <1> 	jmp	error
  3158                              <1> sysfork_2: ; 1:
  3159 00003E28 E83BF0FFFF          <1> 	call	allocate_page
  3160                              <1> 	;jc	error
  3161                              <1> 	; 08/01/2022
  3162 00003E2D 72F4                <1> 	jc	short sysfork_0
  3163                              <1> 
  3164 00003E2F 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3165                              <1> 	; Retro UNIX 386 v1 modification!
  3166 00003E30 E82CF2FFFF          <1> 	call	duplicate_page_dir
  3167                              <1> 		; EAX = New page directory 
  3168 00003E35 7308                <1> 	jnc	short sysfork_3
  3169 00003E37 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3170 00003E38 E8F3F1FFFF          <1> 	call 	deallocate_page
  3171                              <1> 	;jmp	error
  3172                              <1> 	; 08/01/2022
  3173 00003E3D EBE4                <1> 	jmp	short sysfork_0  ; error
  3174                              <1> sysfork_3:
  3175                              <1> 	; Retro UNIX 386 v1 modification !
  3176 00003E3F 56                  <1> 	push	esi
  3177 00003E40 E82F0F0000          <1> 	call	wswap ; save current user (u) structure, user registers
  3178                              <1> 		      ; and interrupt return components (for IRET)
  3179 00003E45 8705[046F0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3180 00003E4B A3[086F0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3181 00003E50 5E                  <1> 	pop	esi
  3182 00003E51 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3183                              <1> 		; [u.usp] = esp
  3184 00003E52 89F7                <1> 	mov	edi, esi
  3185                              <1> 	;shl	di, 2
  3186                              <1> 	; 08/01/2022
  3187 00003E54 C1E702              <1> 	shl	edi, 2
  3188 00003E57 8987[1C6C0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3189 00003E5D A3[006F0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3190                              <1> 	; 28/08/2015
  3191 00003E62 0FB605[F56E0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3192                              <1> 		; movb u.uno,-(sp) / save parent process number
  3193 00003E69 89C7                <1> 	mov	edi, eax
  3194 00003E6B 50                  <1>         push	eax ; ** 
  3195 00003E6C 8A87[DF6B0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3196                              <1> 	; 18/09/2015
  3197                              <1> 	;mov	[esi+p.ttyc-1], al ; set child's console tty
  3198                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3199 00003E72 668986[DF6B0000]    <1> 	mov     [esi+p.ttyc-1], ax ; al - set child's console tty
  3200                              <1> 				   ; ah - reset child's wait channel	
  3201 00003E79 89F0                <1> 	mov	eax, esi
  3202 00003E7B A2[F56E0000]        <1> 	mov	[u.uno], al ; child process number
  3203                              <1> 		;movb r1,u.uno / set child process number to r1
  3204 00003E80 FE86[0F6C0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3205                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3206                              <1> 				; / process to active status
  3207                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3208                              <1> 			      ; / control tty buffer in r2
  3209                              <1>                 ; beq 2f / branch, if no such tty assigned
  3210                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3211                              <1> 	; 2:
  3212 00003E86 53                  <1> 	push	ebx  ; * return address for the child process
  3213                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3214                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3215                              <1> 		; mov $runq+4,r2
  3216 00003E87 E83E0F0000          <1> 	call	putlu 
  3217                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3218                              <1> 			   ; / run queue
  3219                              <1> 	; 08/01/2022
  3220 00003E8C D1E6                <1> 	shl	esi, 1
  3221                              <1> 	;shl	si, 1
  3222                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3223                              <1> 		       ; / into p.pid table
  3224 00003E8E 66FF05[8A6E0000]    <1> 	inc	word [mpid]
  3225                              <1> 		; inc mpid / increment m.pid; get a new process name
  3226 00003E95 66A1[8A6E0000]      <1> 	mov	ax, [mpid]
  3227 00003E9B 668986[7E6B0000]    <1> 	mov	[esi+p.pid-2], ax
  3228                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3229                              <1> 				    ; / in child process' name slot
  3230 00003EA2 5A                  <1> 	pop	edx  ; * return address for the child process
  3231                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3232 00003EA3 5B                  <1>   	pop	ebx  ; **
  3233                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3234                              <1> 		; movb (sp),r2 / put parent process number in r2
  3235                              <1> 	; 08/01/2022
  3236 00003EA4 D1E3                <1> 	shl	ebx, 1
  3237                              <1> 	;shl 	bx, 1
  3238                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3239                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3240 00003EA6 668B83[7E6B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3241                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3242                              <1> 				   ; / process
  3243 00003EAD 668986[9E6B0000]    <1> 	mov	[esi+p.ppid-2], ax
  3244                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3245                              <1> 			  ; / in parent process slot for child
  3246 00003EB4 A3[A46E0000]        <1> 	mov	[u.r0], eax	
  3247                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3248                              <1> 			     ; / at location where r0 was saved
  3249 00003EB9 8B2D[9C6E0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3250 00003EBF 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3251                              <1> 			   ; * return address for the child process
  3252                              <1> 		; mov $sysret1,-(sp) /
  3253                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3254                              <1> 			      ; / user is swapped out
  3255                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3256                              <1> 	; 04/09/2015 - 01/09/2015
  3257                              <1> 	; [u.usp] = esp
  3258 00003EC2 68[CC3B0000]        <1> 	push	sysret ; ***
  3259 00003EC7 8925[A06E0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3260                              <1> 			     ; (for child process)	
  3261 00003ECD 31C0                <1> 	xor 	eax, eax
  3262 00003ECF 66A3[DA6E0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3263                              <1> 	;
  3264 00003ED5 E89A0E0000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3265                              <1> 		;jsr r0,wswap / put child process out on drum
  3266                              <1> 		;jsr r0,unpack / unpack user stack
  3267                              <1> 		;mov u.usp,sp / restore user stack pointer
  3268                              <1> 		; tst (sp)+ / bump stack pointer
  3269                              <1> 	; Retro UNIX 386 v1 modification !
  3270 00003EDA 58                  <1> 	pop	eax ; ***
  3271                              <1> 	; 08/01/2022
  3272 00003EDB D1E3                <1> 	shl	ebx, 1
  3273                              <1> 	;shl 	bx, 1
  3274 00003EDD 8B83[1C6C0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3275 00003EE3 E8B50E0000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3276                              <1> 		      ; registers and return address (for IRET)
  3277                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3278 00003EE8 0FB705[8A6E0000]    <1>         movzx   eax, word [mpid]
  3279 00003EEF A3[A46E0000]        <1> 	mov	[u.r0], eax
  3280                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3281                              <1> 			       ; / where r0 was saved
  3282                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3283                              <1> 			          ; / process return
  3284                              <1> 	;xor	ebx, ebx
  3285 00003EF4 31F6                <1> 	xor     esi, esi
  3286                              <1> 		;clr r1
  3287                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3288                              <1> 	      ; / opened by the parent process
  3289                              <1> 	; 08/01/2022
  3290                              <1> 	; 01/09/2015
  3291 00003EF6 30FF                <1> 	xor	bh, bh
  3292 00003EF8 8A9E[AE6E0000]      <1> 	mov 	bl, [esi+u.fp]
  3293                              <1> 	; 08/01/2022
  3294                              <1> 	;mov 	al, [esi+u.fp]
  3295                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3296 00003EFE 08DB                <1> 	or	bl, bl
  3297                              <1> 	; 08/01/2022
  3298                              <1> 	;or	al, al
  3299 00003F00 7409                <1> 	jz	short sysfork_5	
  3300                              <1> 		; beq 2f / file has not been opened by parent, 
  3301                              <1> 		       ; / so branch
  3302                              <1> 	;mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3303                              <1> 	; 08/01/2022
  3304                              <1> 	;mov	ah, 16 ; Retro UNIX 386 v2 fsp structure size = 16 bytes
  3305                              <1> 	;mul	ah
  3306                              <1> 	;;movzx	ebx, ax
  3307                              <1> 	;mov	bx, ax
  3308                              <1> 	;mov	ebx, eax ; 08/01/2022
  3309                              <1> 	;shl	bx, 3
  3310                              <1> 		; asl r2 / multiply by 8
  3311                              <1>        		; asl r2 / to get index into fsp table
  3312                              <1>        		; asl r2
  3313                              <1> 	; 08/01/2022
  3314 00003F02 C1E304              <1> 	shl	ebx, 4 ; multiply by 16
  3315                              <1> 	; 08/01/2022
  3316 00003F05 FE83[366B0000]      <1> 	inc	byte [ebx+fsp-10] ; Retro UNIX 386 v2 fs fsp structure
  3317                              <1>   	;inc	byte [ebx+fsp-2]
  3318                              <1> 		; incb fsp-2(r2) / increment number of processes
  3319                              <1> 			     ; / using file, because child will now be
  3320                              <1> 			     ; / using this file
  3321                              <1> sysfork_5: ; 2:
  3322 00003F0B 46                  <1>         inc     esi
  3323                              <1> 		; inc r1 / get next open file
  3324 00003F0C 6683FE0A            <1>         cmp     si, 10
  3325                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3326                              <1> 			  ; / can be opened
  3327 00003F10 72E4                <1> 	jb	short sysfork_4	
  3328                              <1> 		; blt 1b / check next entry
  3329 00003F12 E9B5FCFFFF          <1> 	jmp	sysret
  3330                              <1> 		; br sysret1
  3331                              <1> 
  3332                              <1> sysread: ; < read from file >
  3333                              <1> 	; 24/12/2021
  3334                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3335                              <1> 	; 27/03/2020
  3336                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3337                              <1> 	; 13/05/2015
  3338                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3339                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3340                              <1> 	;
  3341                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3342                              <1> 	; characters to be read. If finds the file from the file
  3343                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3344                              <1> 	; is returned from a successful open call (sysopen).
  3345                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3346                              <1> 	; is read into core via 'readi'.
  3347                              <1> 	;
  3348                              <1> 	; Calling sequence:
  3349                              <1> 	;	sysread; buffer; nchars
  3350                              <1> 	; Arguments:
  3351                              <1> 	;	buffer - location of contiguous bytes where 
  3352                              <1> 	;		 input will be placed.
  3353                              <1> 	;	nchars - number of bytes or characters to be read.
  3354                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3355                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3356                              <1> 	; ...............................................................
  3357                              <1> 	;				
  3358                              <1> 	; Retro UNIX 8086 v1 modification: 
  3359                              <1> 	;       'sysread' system call has three arguments; so,
  3360                              <1> 	;	* 1st argument, file descriptor is in BX register
  3361                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3362                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3363                              <1> 	;
  3364                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3365                              <1> 	;	to the user with number of bytes read. 
  3366                              <1> 	;
  3367                              <1> 
  3368                              <1> ; temporary ! - 26/12/2021
  3369 00003F17 C605[6F3F0000]52    <1> mov byte [srwtype], 'R'
  3370                              <1> 
  3371 00003F1E E859000000          <1> 	call	rw1
  3372                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3373                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3374                              <1>        	; 04/12/2021
  3375 00003F23 7221                <1> 	jc	short sysread_err
  3376 00003F25 7549                <1> 	jnz	short rw3 ; error ! (permission denied)
  3377                              <1> 	;		; read a file while it is open for write!
  3378                              <1> 
  3379                              <1> 	; eax = inode number
  3380                              <1> 
  3381                              <1> 	; 04/12/2021
  3382                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3383                              <1> 	;test	ah, 80h
  3384                              <1> 	;	; tst r1 / negative i-number?
  3385                              <1> 	;;jnz	error
  3386                              <1> 	;;	; ble error1 / yes, error 1 to read
  3387                              <1> 	;;		   ; / it should be positive
  3388                              <1> 	;; 04/12/2021
  3389                              <1> 	;jnz	short sysread_err
  3390                              <1> 
  3391                              <1> ; temporary - 26/12/2021
  3392 00003F27 53                  <1> push	ebx
  3393 00003F28 50                  <1> push	eax
  3394 00003F29 B058                <1> mov	al, 'X'
  3395 00003F2B B44E                <1> mov	ah, 4Eh	
  3396 00003F2D 8B1D[E1400000]      <1> mov	ebx, [openaddr]
  3397 00003F33 8005[E1400000]02    <1> add	byte [openaddr], 2
  3398 00003F3A 668903              <1> mov	word [ebx], ax
  3399 00003F3D 58                  <1> pop	eax
  3400 00003F3E 5B                  <1> pop	ebx
  3401                              <1> 
  3402 00003F3F E87B160000          <1> 	call	readi
  3403                              <1> 		; jsr r0,readi / read data into core
  3404 00003F44 EB1A                <1> 	jmp	short rw0
  3405                              <1> 		; br 1f
  3406                              <1> sysread_err:
  3407                              <1> syswrite_err:
  3408                              <1> 	; 04/12/2021
  3409 00003F46 E961FCFFFF          <1> 	jmp	error
  3410                              <1> 
  3411                              <1> syswrite: ; < write to file >
  3412                              <1> 	; 24/12/2021
  3413                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3414                              <1> 	; 27/03/2020
  3415                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3416                              <1> 	; 13/05/2015
  3417                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3418                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3419                              <1> 	;
  3420                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3421                              <1> 	; and the number of characters to write. If finds the file
  3422                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3423                              <1> 	; descriptor is returned from a successful open or create call
  3424                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3425                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3426                              <1> 	;
  3427                              <1> 	; Calling sequence:
  3428                              <1> 	;	syswrite; buffer; nchars
  3429                              <1> 	; Arguments:
  3430                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3431                              <1> 	;	nchars - number of characters to be written.
  3432                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3433                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3434                              <1> 	; ...............................................................
  3435                              <1> 	;				
  3436                              <1> 	; Retro UNIX 8086 v1 modification: 
  3437                              <1> 	;       'syswrite' system call has three arguments; so,
  3438                              <1> 	;	* 1st argument, file descriptor is in BX register
  3439                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3440                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3441                              <1> 	;
  3442                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3443                              <1> 	;	to the user with number of bytes written. 
  3444                              <1> 	;
  3445                              <1> 
  3446                              <1> ; temporary ! - 26/12/2021
  3447 00003F4B C605[6F3F0000]56    <1> mov byte [srwtype], 'V'
  3448                              <1> 
  3449 00003F52 E825000000          <1> 	call	rw1
  3450                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3451                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3452                              <1>        	; 04/12/2021
  3453 00003F57 72ED                <1> 	jc	short syswrite_err
  3454 00003F59 7415                <1> 	jz	short rw3 ; error ! (permission denied)
  3455                              <1> 			; write to a file while it is open for read
  3456                              <1> 	; eax = inode number
  3457                              <1> 	
  3458                              <1> 	; 04/12/2021
  3459                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3460                              <1> 	;test	ah, 80h
  3461                              <1> 	;	; tst r1 / positive i-number ?
  3462                              <1>         ;jz	short rw3 ; 13/05/2015
  3463                              <1> 	;;jz	error
  3464                              <1> 	;	; bge error1 / yes, error 1 
  3465                              <1> 	;		   ; / negative i-number means write
  3466                              <1>         ;neg	ax
  3467                              <1> 	;	; neg r1 / make it positive
  3468                              <1> 	
  3469 00003F5B E870180000          <1> 	call	writei
  3470                              <1>         	; jsr r0,writei / write data
  3471                              <1> rw0: ; 1:
  3472 00003F60 A1[D06E0000]        <1>         mov	eax, [u.nread]
  3473 00003F65 A3[A46E0000]        <1> 	mov	[u.r0], eax
  3474                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3475                              <1> 				  ; / into (u.r0)
  3476 00003F6A E95DFCFFFF          <1> 	jmp	sysret
  3477                              <1>         	; br sysret1
  3478                              <1> 
  3479                              <1> ; temporary - 26/12/2021
  3480 00003F6F 00                  <1> srwtype: db 0
  3481                              <1> 
  3482                              <1> rw3: 
  3483                              <1> ; temporary - 26/12/2021
  3484                              <1> ;mov dword [0B8000h], 4E354E35h
  3485                              <1> ;mov ecx, 0FFFFh
  3486                              <1> ;aboveysx:
  3487                              <1> ;dec edx
  3488                              <1> ;inc edx
  3489                              <1> ;loop aboveysx
  3490                              <1> ;stc
  3491                              <1> ;rw4:
  3492                              <1> 	; 13/05/2015
  3493 00003F70 C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3493 00003F78 0000                <1>
  3494                              <1> 	;stc
  3495                              <1> 	;retn
  3496                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.2
  3497 00003F7A EBCA                <1> 	jmp	short syswrite_err
  3498                              <1> 
  3499                              <1> rw1:	
  3500                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3501                              <1> 	; 27/03/2020
  3502                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3503                              <1> 	; 14/05/2015
  3504                              <1> 	; 13/05/2015
  3505                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3506                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3507                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3508                              <1> 	;
  3509                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3510                              <1> 				;(in the user's virtual memory space)
  3511                              <1> 	;mov	[u.count], edx 
  3512                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3513                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3514                              <1> 	;;mov	eax, ebx ; file descriptor
  3515                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3516                              <1> 		             ; / (index to u.fp table) in r1
  3517                              <1> 	; 13/05/2015
  3518 00003F7C C705[A46E0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3518 00003F84 0000                <1>
  3519                              <1> 	;
  3520                              <1> 	;; call	getf
  3521                              <1>         ; ebx = File descriptor
  3522 00003F86 E8EA080000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3523                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3524                              <1> 	; AX = I-number of the file ; negative i-number means write
  3525                              <1> 
  3526                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3527                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3528                              <1> 	; BL = open mode & status flag (0 = read, 1 = write)
  3529                              <1> 	; eax = inode number (ax)
  3530                              <1> 	; 27/03/2020
  3531                              <1> 	; [cdev] = logical drive number 	
  3532                              <1> 
  3533                              <1> 	; 13/05/2015
  3534 00003F8B 6683F801            <1> 	cmp 	ax, 1
  3535 00003F8F 7237                <1> 	jb	short rw2
  3536                              <1> 	;
  3537 00003F91 890D[C86E0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3538                              <1> 				;(in the user's virtual memory space)
  3539 00003F97 8915[CC6E0000]      <1> 	mov	[u.count], edx 
  3540                              <1> 	; 14/05/2015
  3541 00003F9D C705[186F0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3541 00003FA5 0000                <1>
  3542                              <1> 
  3543                              <1> 
  3544                              <1> ; temporary - 27/12/2021
  3545 00003FA7 08DB                <1> or	bl, bl
  3546 00003FA9 7519                <1> jnz	short ghi
  3547 00003FAB 50                  <1> push	eax
  3548 00003FAC B44E                <1> mov	ah, 4Eh
  3549 00003FAE B052                <1> mov	al, 'R'
  3550 00003FB0 66A304800B00        <1> mov	word [0B8004h], ax
  3551 00003FB6 A0[E5400000]        <1> mov	al, [bytype]
  3552 00003FBB 0430                <1> add	al, '0'
  3553 00003FBD 66A306800B00        <1> mov	word [0B8006h], ax
  3554 00003FC3 58                  <1> pop	eax
  3555                              <1> ghi:
  3556                              <1> 
  3557                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3558                              <1> 	; 27/03/2020 - Retro UNIX 386 v2
  3559 00003FC4 80E301              <1> 	and	bl, 1
  3560                              <1> 		; zf = 0 -> open for write	
  3561                              <1> 		; zf = 1 -> open for read
  3562                              <1> 	;
  3563 00003FC7 C3                  <1> 	retn
  3564                              <1>         	; rts r0
  3565                              <1> rw2:
  3566                              <1> ; temporary - 25/12/2021
  3567 00003FC8 C70500800B00344E34- <1> mov dword [0B8000h], 4E344E34h
  3567 00003FD1 4E                  <1>
  3568 00003FD2 B9FFFF0000          <1> mov ecx, 0FFFFh
  3569                              <1> abovexsx:
  3570 00003FD7 4A                  <1> dec edx
  3571 00003FD8 42                  <1> inc edx
  3572 00003FD9 E2FC                <1> loop abovexsx
  3573 00003FDB F9                  <1> stc
  3574                              <1> 	; 13/05/2015
  3575 00003FDC C705[186F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3575 00003FE4 0000                <1>
  3576 00003FE6 C3                  <1> 	retn
  3577                              <1> 
  3578                              <1> 	; 08/01/2022
  3579                              <1> 	; 02/01/2022
  3580                              <1> 	; 01/01/2022
  3581                              <1> 	; 27/12/2021
  3582                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility code
  3583                              <1> sysopen: ;<open file>
  3584                              <1> 	; 04/12/2021
  3585                              <1> 	; 07/08/2020 (Retro UNIX 386 v2)
  3586                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3587                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3588                              <1> 	;
  3589                              <1> 	; 'sysopen' opens a file in following manner:
  3590                              <1> 	;    1) The second argument in a sysopen says whether to
  3591                              <1> 	;	open the file ro read (0) or write (>0).
  3592                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3593                              <1> 	;    3) The file is opened by 'iopen'.
  3594                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3595                              <1> 	;	and the user's open file list - u.fp.
  3596                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3597                              <1> 	;	b) An entry for the file is created in the fsp table.
  3598                              <1> 	;	c) The number of this entry is put on u.fp list.
  3599                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3600                              <1> 	;	   to by u.r0.
  3601                              <1> 	;
  3602                              <1> 	; Calling sequence:
  3603                              <1> 	;	sysopen; name; mode
  3604                              <1> 	; Arguments:
  3605                              <1> 	;	name - file name or path name
  3606                              <1> 	;	mode - 0 to open for reading
  3607                              <1> 	;	       1 to open for writing
  3608                              <1> 	; Inputs: (arguments)
  3609                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3610                              <1> 	;		  is put into r0's location on the stack.	
  3611                              <1> 	; ...............................................................
  3612                              <1> 	;				
  3613                              <1> 	; Retro UNIX 8086 v1 modification: 
  3614                              <1> 	;       'sysopen' system call has two arguments; so,
  3615                              <1> 	;	* 1st argument, name is pointed to by BX register
  3616                              <1> 	;	* 2nd argument, mode is in CX register
  3617                              <1> 	;
  3618                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3619                              <1> 	;	to the user with the file descriptor/number 
  3620                              <1> 	;	(index to u.fp list).
  3621                              <1> 	;
  3622                              <1> 	;call	arg2
  3623                              <1> 	; * name - 'u.namep' points to address of file/path name
  3624                              <1> 	;          in the user's program segment ('u.segmnt')
  3625                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3626                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3627                              <1> 	;          which is on top of stack.
  3628                              <1> 	;
  3629                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3630                              <1> 	;
  3631                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3632                              <1> 
  3633 00003FE7 891D[C06E0000]      <1> 	mov	[u.namep], ebx
  3634 00003FED 51                  <1> 	push	ecx ; * ; 04/12/2021 (cx -> ecx)
  3635 00003FEE E8EF080000          <1> 	call	namei
  3636                              <1> 		; jsr r0,namei / i-number of file in r1
  3637                              <1>      	;and	ax, ax
  3638                              <1> 	;jz	error ; File not found
  3639 00003FF3 722B                <1> 	jc	short fnotfound ; 14/05/2015
  3640                              <1> 	;jc	error ; 27/05/2013
  3641                              <1> 		; br  error2 / file not found
  3642                              <1>    	;pop	edx ; * ; mode ; 04/12/2021
  3643                              <1> 	;push	edx ; *
  3644                              <1> 	;;or	dx, dx
  3645                              <1> 	;or	dl, dl
  3646                              <1> 	;	; tst (sp) / is mode = 0 (2nd arg of call;
  3647                              <1> 	;	         ; / 0 means, open for read)
  3648                              <1> 	;;jz	short sysopen_0
  3649                              <1> 	;;	; beq 1f / yes, leave i-number positive
  3650                              <1> 	
  3651 00003FF5 8B1424              <1> 	mov	edx, [esp] ; *
  3652                              <1> 	; edx = open mode (0 or 1)
  3653                              <1> 
  3654                              <1> ;syscreat_0: ;op0: ; 27/12/2015
  3655                              <1> ;	neg	ax
  3656                              <1> ;        	; neg r1 / open for writing so make i-number negative
  3657                              <1> 
  3658                              <1> sysopen_0: ;1:
  3659 00003FF8 E89E1B0000          <1> 	call	iopen
  3660                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3661 00003FFD 5A                  <1> 	pop	edx ; * ; mode ; 04/12/2021
  3662                              <1> 	;;and	dx, dx
  3663                              <1> 	;and	dl, dl
  3664                              <1>         ;	; tst (sp)+ / pop the stack and test the mode
  3665                              <1> 	;jz	short sysopen_2
  3666                              <1>         ;	; beq op1 / is open for read op1
  3667                              <1> ;sysopen_1: ;op0:
  3668                              <1> 	;neg	ax
  3669                              <1>         ;	; neg r1 
  3670                              <1> 	;	     ;/ make i-number positive if open for writing [???]
  3671                              <1> 
  3672                              <1> 	;; NOTE: iopen always make i-number positive.
  3673                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3674                              <1> sysopen_1: ; 04/12/2021
  3675                              <1> sysopen_2: ;op1:
  3676 00003FFE 31F6                <1>         xor     esi, esi
  3677                              <1>         	; clr r2 / clear registers
  3678 00004000 31DB                <1>         xor     ebx, ebx
  3679                              <1> 		; clr r3
  3680                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3681 00004002 389E[AE6E0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3682                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3683 00004008 7625                <1> 	jna	short sysopen_4_temp ; temporary - 26/12/2021 
  3684                              <1> 	;jna	short sysopen_4
  3685                              <1> 		; beq 1f / if byte in list is 0 branch
  3686 0000400A 46                  <1>         inc     esi
  3687                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3688                              <1> 	; 02/01/2022
  3689                              <1> 	;cmp	si, OPENFILES ; 04/12/2021
  3690 0000400B 6683FE0A            <1> 	cmp	si, 10
  3691                              <1> 		; cmp r2,$10. / reached end of list?
  3692 0000400F 72F1                <1> 	jb	short sysopen_3
  3693                              <1> 		; blt 1b / no, go back
  3694                              <1> toomanyf:
  3695                              <1> 	; 14/05/2015
  3696 00004011 C705[186F0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3696 00004019 0000                <1>
  3697 0000401B E98CFBFFFF          <1> 	jmp	error
  3698                              <1>         	; br error2 / yes, error (no files open)
  3699                              <1> fnotfound: 
  3700                              <1> 	; 14/05/2015
  3701 00004020 C705[186F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3701 00004028 0000                <1>
  3702 0000402A E97DFBFFFF          <1> 	jmp	error
  3703                              <1> 
  3704                              <1> ; temporary - 26/12/2021
  3705                              <1> sysopen_4_temp:
  3706 0000402F 89F3                <1> 	mov	ebx, esi 
  3707 00004031 881D[E5400000]      <1> 	mov	[bytype], bl
  3708 00004037 31DB                <1> 	xor	ebx, ebx
  3709                              <1> 
  3710                              <1> sysopen_4: ; 1:
  3711 00004039 6683BB[406B0000]00  <1>         cmp     word [ebx+fsp], 0
  3712                              <1> 		; tst fsp(r3) / scan fsp entries
  3713 00004041 760D                <1>         jna     short sysopen_5
  3714                              <1> 		; beq 1f / if 0 branch
  3715                              <1> 	;; 14/05/2015 - Retro UNIX 386 v1 modification !
  3716                              <1> 	;add	bx, 10 ; fsp structure size = 10 bytes/entry
  3717                              <1> 		; add $8.,r3 / add 8 to r3 
  3718                              <1> 			; / to bump it to next entry mfsp table
  3719                              <1> 	; 01/01/2022
  3720                              <1> 	; 07/08/2020 - Retro UNIX 386 v2
  3721 00004043 6683C310            <1> 	add	bx, 16 ; fsp structure size = 16 bytes/entry ; runix v2
  3722                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  3723                              <1> 	;add	bx, fp.size
  3724                              <1> 
  3725                              <1> 	; 22/11/2021
  3726                              <1> 	;cmp	bx, NFILES*fp.size ; NFILES*16
  3727                              <1> 	; 02/01/2022
  3728 00004047 6681FB2003          <1> 	cmp	bx, nfiles*16
  3729                              <1> 	; 01/01/2022
  3730                              <1> 	;cmp	bx, NFILES*16 ; NFILES*fp.size
  3731                              <1> 	;;cmp	bx, nfiles*10
  3732                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3733 0000404C 72EB                <1> 	jb	short sysopen_4
  3734                              <1>        		; blt 1b / no, back
  3735                              <1> 	;jmp	error
  3736                              <1>         ;	; br error2 / yes, error
  3737                              <1> 	; 04/12/2021
  3738                              <1> 	; 07/08/2020
  3739 0000404E EBC1                <1> 	jmp	short toomanyf
  3740                              <1> 
  3741                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3742 00004050 668983[406B0000]    <1>         mov     [ebx+fsp], ax
  3743                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3744                              <1> 			; / into next available entry in fsp table,
  3745                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3746                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3747                              <1> 	;	; mov cdev,fsp+2(r3) / put # of device in next word
  3748                              <1> 
  3749                              <1> ; temporary - 01/01/2022
  3750 00004057 53                  <1> push	ebx
  3751 00004058 B44E                <1> mov	ah, 4Eh
  3752 0000405A B057                <1> mov	al, 'W'
  3753 0000405C 08D2                <1> or	dl, dl
  3754 0000405E 7502                <1> jnz	short tyu
  3755 00004060 B052                <1> mov	al, 'R'
  3756                              <1> tyu:
  3757 00004062 8B1D[E1400000]      <1> mov	ebx, [openaddr]
  3758 00004068 8005[E1400000]02    <1> add	byte [openaddr], 2
  3759 0000406F 668903              <1> mov	word [ebx], ax
  3760 00004072 8B1D[E1400000]      <1> mov	ebx, [openaddr]
  3761 00004078 8005[E1400000]02    <1> add	byte [openaddr], 2
  3762 0000407F A0[E5400000]        <1> mov	al, [bytype]
  3763 00004084 0430                <1> add	al, '0'
  3764 00004086 668903              <1> mov	word [ebx], ax
  3765 00004089 8B1C24              <1> mov	ebx, [esp]
  3766 0000408C C1EB04              <1> shr	ebx, 4
  3767 0000408F 88D8                <1> mov	al, bl
  3768 00004091 0430                <1> add	al, '0'
  3769 00004093 8B1D[E1400000]      <1> mov	ebx, [openaddr]
  3770 00004099 8005[E1400000]02    <1> add	byte [openaddr], 2
  3771 000040A0 668903              <1> mov	[ebx], ax
  3772 000040A3 51                  <1> push	ecx
  3773 000040A4 B9FFFFFF00          <1> mov	ecx, 0FFFFFFh
  3774                              <1> gjl:
  3775 000040A9 48                  <1> dec	eax
  3776 000040AA 40                  <1> inc	eax
  3777 000040AB E2FC                <1> loop	gjl
  3778 000040AD 59                  <1> pop	ecx
  3779 000040AE 5B                  <1> pop	ebx
  3780                              <1> 
  3781                              <1> 	; 04/12/2021        
  3782 000040AF A0[856E0000]        <1> 	mov	al, [cdev]
  3783 000040B4 88D4                <1> 	mov	ah, dl ; open mode, 0 = read, 1 = write
  3784 000040B6 668983[446B0000]    <1> 	mov	[ebx+fsp+4], ax ; device number & open mode
  3785                              <1> 
  3786                              <1> 	;xor	edi, edi
  3787                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3788                              <1> 	;	; clr fsp+4(r3)
  3789                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3790                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3791                              <1> 
  3792                              <1> 	; 04/12/2021 
  3793 000040BD 31C0                <1> 	xor	eax, eax
  3794 000040BF 8983[486B0000]      <1>   	mov	[ebx+fsp+8], eax ; offset pointer = 0
  3795                              <1> 	;inc	word [ebx+fsp+6]
  3796 000040C5 FE83[466B0000]      <1> 	inc	byte [ebx+fsp+6] ; open count = open count + 1	
  3797                              <1> 
  3798                              <1>   	;mov	eax, ebx
  3799                              <1> 	;mov	bl, 10
  3800                              <1> 	;div	bl 
  3801                              <1> 	;	; asr r3
  3802                              <1> 	;	; asr r3 / divide by 8 
  3803                              <1> 	;	; asr r3 ; / to get number of the fsp entry-1
  3804                              <1> 	;inc	al
  3805                              <1>         ;	; inc r3 / add 1 to get fsp entry number
  3806                              <1>         ;mov	[esi+u.fp], al
  3807                              <1> 	;	; movb r3,u.fp(r2) / move entry number into 
  3808                              <1> 			; / next available slot in u.fp list
  3809                              <1> 	; 04/12/2021
  3810 000040CB C1EB04              <1> 	shr	ebx, 4	; / 16
  3811                              <1> 	;shr	bx, 4	; bx = fsp entry number (index)	
  3812                              <1> 			; bx <= 49 for current runix 386 version
  3813 000040CE FEC3                <1> 	inc 	bl	; bl = 1 to 50
  3814 000040D0 889E[AE6E0000]      <1> 	mov	[esi+u.fp], bl 	
  3815                              <1> 
  3816 000040D6 8935[A46E0000]      <1>         mov     [u.r0], esi
  3817                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3818                              <1> 			     ; / into r0 loc on stack
  3819 000040DC E9EBFAFFFF          <1>         jmp	sysret
  3820                              <1> 		; br sysret2
  3821                              <1> 
  3822                              <1> ; temporary - 01/01/2022
  3823 000040E1 00800B00            <1> openaddr: dd 0B8000h
  3824 000040E5 00                  <1> bytype:	db 0 
  3825                              <1> 
  3826                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  3827                              <1> ;
  3828                              <1> ;         15                    7                   0
  3829                              <1> ;  1     |-------------------------------------------|
  3830                              <1> ;        |   	     i-number of open file           |
  3831                              <1> ;        |-------------------------------------------| 
  3832                              <1> ;        |        high word of 32 bit i-number       |
  3833                              <1> ;        |-------------------------------------------|
  3834                              <1> ;        | open mode & status  |   device number     |
  3835                              <1> ;        |-------------------------------------------|			
  3836                              <1> ;        |    reserved byte    |     open count      |
  3837                              <1> ;        |-------------------------------------------| 
  3838                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3839                              <1> ;        |-------------------------------------------|
  3840                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3841                              <1> ;        |-------------------------------------------|
  3842                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3843                              <1> ;        |-------------------------------------------|
  3844                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3845                              <1> ;        |-------------------------------------------|
  3846                              <1> ;  2     |                                           |
  3847                              <1> ;        |-------------------------------------------| 
  3848                              <1> ;        |                                           |
  3849                              <1> ;        |-------------------------------------------|
  3850                              <1> ;        |                                           |
  3851                              <1> ;        |-------------------------------------------|
  3852                              <1> ;        |                                           |
  3853                              <1> ;        |-------------------------------------------| 
  3854                              <1> ;        |                                           | 
  3855                              <1> 
  3856                              <1> 	;
  3857                              <1> 	; 'fsp' table (10 bytes/entry)
  3858                              <1> 	; bit 15				   bit 0
  3859                              <1> 	; ---|-------------------------------------------
  3860                              <1> 	; r/w|		i-number of open file
  3861                              <1> 	; ---|-------------------------------------------
  3862                              <1> 	;		   device number
  3863                              <1> 	; -----------------------------------------------
  3864                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3865                              <1> 	; -----------------------------------------------
  3866                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3867                              <1> 	; ----------------------|------------------------
  3868                              <1> 	;  flag that says file 	| number of processes
  3869                              <1> 	;   has been deleted	| that have file open 
  3870                              <1> 	; ----------------------|------------------------
  3871                              <1> 	;
  3872                              <1> 
  3873                              <1> ; temporary - 01/01/2022
  3874                              <1> %if 0
  3875                              <1> 
  3876                              <1> 	; 01/01/2022
  3877                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3878                              <1> syscreat: ; < create file >
  3879                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3880                              <1> 	; 04/04/2021
  3881                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3882                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3883                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3884                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3885                              <1> 	;
  3886                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3887                              <1> 	; u.namep points to name of the file and mode is put
  3888                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3889                              <1> 	; If the file aready exists, it's mode and owner remain 
  3890                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3891                              <1> 	; did not exist, an i-node is created with the new mode via
  3892                              <1> 	; 'maknod' whether or not the file already existed, it is
  3893                              <1> 	; open for writing. The fsp table is then searched for a free
  3894                              <1> 	; entry. When a free entry is found, proper data is placed
  3895                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3896                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3897                              <1> 	; is put in the user's r0. 			
  3898                              <1> 	;
  3899                              <1> 	; Calling sequence:
  3900                              <1> 	;	syscreate; name; mode
  3901                              <1> 	; Arguments:
  3902                              <1> 	;	name - name of the file to be created
  3903                              <1> 	;	mode - mode of the file to be created
  3904                              <1> 	; Inputs: (arguments)
  3905                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3906                              <1> 	;		   (the file descriptor of new file)
  3907                              <1> 	; ...............................................................
  3908                              <1> 	;				
  3909                              <1> 	; Retro UNIX 8086 v1 modification: 
  3910                              <1> 	;       'syscreate' system call has two arguments; so,
  3911                              <1> 	;	* 1st argument, name is pointed to by BX register
  3912                              <1> 	;	* 2nd argument, mode is in CX register
  3913                              <1> 	;
  3914                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3915                              <1> 	;	to the user with the file descriptor/number 
  3916                              <1> 	;	(index to u.fp list).
  3917                              <1> 	;
  3918                              <1> 	;call	arg2
  3919                              <1> 	; * name - 'u.namep' points to address of file/path name
  3920                              <1> 	;          in the user's program segment ('u.segmnt')
  3921                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3922                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3923                              <1> 	;          which is on top of stack.
  3924                              <1> 	;
  3925                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3926                              <1> 			    ; / on stack
  3927                              <1> 	mov	[u.namep], ebx ; file name address
  3928                              <1> 	;push	cx ; mode
  3929                              <1> 	; 04/12/2021
  3930                              <1> 	push	ecx ; cx = mode (permission flags)
  3931                              <1> 	call 	namei        	
  3932                              <1> 		; jsr r0,namei / get the i-number
  3933                              <1>         ;and	ax, ax
  3934                              <1> 	;jz	short syscreat_1	       	
  3935                              <1> 	jc	short syscreat_1
  3936                              <1> 		; br  2f / if file doesn't exist 2f
  3937                              <1> 	; 27/12/2015
  3938                              <1> 	;cmp	ax, 41 ; device inode ?
  3939                              <1>         ;jb	syscreat_0 ; yes
  3940                              <1> 	;
  3941                              <1> 	;neg 	ax
  3942                              <1>         ;	; neg r1 / if file already exists make i-number 
  3943                              <1> 		       ; / negative (open for writing)
  3944                              <1> 	; 01/01/2021
  3945                              <1> 	; 27/03/2021
  3946                              <1> 	test	byte [i.flgs+1], 80h ; regular file
  3947                              <1> 	jz	short f_create_error ; device inode !!!
  3948                              <1> 	test	byte [i.flgs+1], 40h ; directory
  3949                              <1> 	jnz	short f_create_error ; directory inode !!!
  3950                              <1> 
  3951                              <1> 	; Truncate existing file
  3952                              <1> ;syscreate_2:
  3953                              <1> 	; 27/03/2021
  3954                              <1> 	;xor	edx, edx ; 0
  3955                              <1> 	;inc	dl ; DL = 1 ; create/truncate (open for write)
  3956                              <1> 	mov	dl, 1
  3957                              <1> 	;
  3958                              <1> 	call	iopen
  3959                              <1>         	; jsr r0,iopen /
  3960                              <1> 	call	itrunc
  3961                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3962                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3963                              <1> 	; 04/12/2021
  3964                              <1> 	pop	ecx 
  3965                              <1> syscreat_2:
  3966                              <1> 	mov	dl, 1 ; open for writing
  3967                              <1>         jmp     sysopen_1
  3968                              <1>         	; br op0
  3969                              <1> syscreat_1: ; 2: / file doesn't exist
  3970                              <1> 	;pop	ax
  3971                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3972                              <1> 	; 27/03/2021
  3973                              <1> 	pop	eax  ; ax = mode (permission flags)
  3974                              <1> 	;xor	ah, ah	
  3975                              <1>         ;	; bic $!377,r1 / clear upper byte
  3976                              <1> 	; 27/03/2021
  3977                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  3978                              <1> 	; clear bits 15,14,13,12,9 of mode (input from user)
  3979                              <1> 	and	ah, 0Dh ; ISUID (800h) & ISGID (400h) & IREAD (100h)
  3980                              <1> 	or	ah, 8Dh	; IFREG (8000h) ; Regular file
  3981                              <1> 	call 	maknod
  3982                              <1>         	; jsr r0,maknod / make an i-node for this file
  3983                              <1> 	;sub	eax, eax ; 04/12/2021
  3984                              <1> 	mov	ax, [u.dirbuf]
  3985                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3986                              <1> 			        ; / for this new file in r1
  3987                              <1> 	; 04/04/2021
  3988                              <1> 	;mov	dl, 1 ; open for writing
  3989                              <1>         ;
  3990                              <1> 	;jmp	sysopen_1
  3991                              <1>         ;	; br op0 / open the file
  3992                              <1> 	; 04/04/2021
  3993                              <1> 	jmp	short syscreat_2
  3994                              <1> 
  3995                              <1> 	; 04/12/2021
  3996                              <1> dir_access_err:
  3997                              <1> 	; 14/05/2015
  3998                              <1> 	;mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3999                              <1> f_create_error:
  4000                              <1> 	; 27/03/2021
  4001                              <1> 	mov	dword [u.error], ERR_PERM_DENIED ; permission denided !	
  4002                              <1> 	jmp	error
  4003                              <1> 
  4004                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4005                              <1> sysmkdir: ; < make directory >
  4006                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4007                              <1> 	; 02/04/2021
  4008                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  4009                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4010                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4011                              <1> 	;
  4012                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  4013                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  4014                              <1> 	; The special entries '.' and '..' are not present.
  4015                              <1> 	; Errors are indicated if the directory already exists or		
  4016                              <1> 	; user is not the super user. 
  4017                              <1> 	;
  4018                              <1> 	; Calling sequence:
  4019                              <1> 	;	sysmkdir; name; mode
  4020                              <1> 	; Arguments:
  4021                              <1> 	;	name - points to the name of the directory
  4022                              <1> 	;	mode - mode of the directory
  4023                              <1> 	; Inputs: (arguments)
  4024                              <1> 	; Outputs: -
  4025                              <1> 	;    (sets 'directory' flag to 1; 
  4026                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  4027                              <1> 	; ...............................................................
  4028                              <1> 	;				
  4029                              <1> 	; Retro UNIX 8086 v1 modification: 
  4030                              <1> 	;       'sysmkdir' system call has two arguments; so,
  4031                              <1> 	;	* 1st argument, name is pointed to by BX register
  4032                              <1> 	;	* 2nd argument, mode is in CX register
  4033                              <1> 	;
  4034                              <1> 		
  4035                              <1> ; / make a directory
  4036                              <1> 
  4037                              <1> 	;call	arg2
  4038                              <1> 	; * name - 'u.namep' points to address of file/path name
  4039                              <1> 	;          in the user's program segment ('u.segmnt')
  4040                              <1> 	;          with offset in BX register (as sysopen argument 1).
  4041                              <1> 	; * mode - sysopen argument 2 is in CX register 
  4042                              <1> 	;          which is on top of stack.
  4043                              <1> 
  4044                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  4045                              <1> 			    ; / on stack
  4046                              <1> 	mov	[u.namep], ebx
  4047                              <1> 	;push	cx ; mode
  4048                              <1> 	; 27/03/2021
  4049                              <1> 	push	ecx ; cx = mode
  4050                              <1> 	call	namei
  4051                              <1>         	; jsr r0,namei / get the i-number
  4052                              <1>         	;     br .+4 / if file not found branch around error
  4053                              <1>         ;xor 	ax, ax
  4054                              <1> 	;jnz	error
  4055                              <1> 	jnc	short dir_exists ; 14/05/2015
  4056                              <1> 	;jnc	error	
  4057                              <1> 		; br  error2 / directory already exists (error)
  4058                              <1> 
  4059                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  4060                              <1>         ;	;tstb u.uid / is user the super user
  4061                              <1> 	;jna	short dir_access_err ; 14/05/2015
  4062                              <1> 	;;jna	error
  4063                              <1>         ;	;bne error2 / no, not allowed
  4064                              <1> 	;pop	ax
  4065                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  4066                              <1> 	;and	ax, 0FFCFh ; 1111111111001111b
  4067                              <1>         ;	;bic $!317,r1 / all but su and ex
  4068                              <1> 	;;or	ax, 4000h ; 1011111111111111b
  4069                              <1> 	;or	ah, 40h ; Set bit 14 to 1
  4070                              <1>         ; 	;bis $40000,r1 / directory flag
  4071                              <1> 
  4072                              <1> 	; 02/04/2021
  4073                              <1> 	;cmp	word [u.uid], 0
  4074                              <1> 	;ja	error
  4075                              <1> 
  4076                              <1> 	; 02/04/2021
  4077                              <1> 	; ('mkdir' procedure will be called from 'maknod'
  4078                              <1> 	; and then 'mkdir' will check write access permission) 
  4079                              <1> 	; ((so, 'access_w' call is not needed here.))
  4080                              <1> 
  4081                              <1> 	;; 02/04/2021
  4082                              <1> 	;; ('make directory' user permission check)
  4083                              <1> 	;; ((current directory's write permission flags
  4084                              <1> 	;;  will be checked against user's 'uid' & gid'))
  4085                              <1> 	;mov	dx, 80h ; IWRITE
  4086                              <1> 	;call	access_w  ; (in 'access', 'u5.s')
  4087                              <1> 	;; (If cpu will return here, the user has write permission)
  4088                              <1> 		
  4089                              <1> 	; 27/03/2021
  4090                              <1> 	pop	eax  ; ax = mode
  4091                              <1> 	; [ii] = current directory's inode number
  4092                              <1> 
  4093                              <1> 	; 27/03/2021
  4094                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  4095                              <1> 	; clear bits 13,12,11,10,9,6,3,0 of mode (input from user)
  4096                              <1> 	;and	ax, 0C1B6h  ; bits 15,14,8,7,5,4,2,1
  4097                              <1> 	and	ax, 01B6h
  4098                              <1> 	or	ah, 0C0h ; IFREG (8000h) + IFDIR (4000h) 
  4099                              <1> 			 ; Directory
  4100                              <1> 	call	maknod
  4101                              <1>         	;jsr r0,maknod / make the i-node for the directory
  4102                              <1> 	jmp	sysret
  4103                              <1>         	;br sysret2 /
  4104                              <1> dir_exists:
  4105                              <1> 	; 27/03/2021
  4106                              <1> 	; (same error number for files and directories)
  4107                              <1> 	; Error Number: 14 (ERR_DIR_EXISTS)
  4108                              <1> 	mov	dword [u.error], ERR_FILE_EXISTS
  4109                              <1> 				; 'file already exists !' error
  4110                              <1> 	; 04/12/2021
  4111                              <1> 	jmp	error
  4112                              <1> ;dir_access_err:
  4113                              <1> ;	; 14/05/2015
  4114                              <1> ;	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  4115                              <1> ;	jmp	error
  4116                              <1> 
  4117                              <1> %endif
  4118                              <1> 
  4119                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4120                              <1> sysclose: ;<close file>
  4121                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4122                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4123                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  4124                              <1> 	;
  4125                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  4126                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  4127                              <1> 	; is put in r1 and 'fclose' is called.
  4128                              <1> 	;
  4129                              <1> 	; Calling sequence:
  4130                              <1> 	;	sysclose
  4131                              <1> 	; Arguments:
  4132                              <1> 	;	-  
  4133                              <1> 	; Inputs: *u.r0 - file descriptor
  4134                              <1> 	; Outputs: -
  4135                              <1> 	; ...............................................................
  4136                              <1> 	;				
  4137                              <1> 	; Retro UNIX 8086 v1 modification:
  4138                              <1> 	;	 The user/application program puts file descriptor
  4139                              <1> 	;        in BX register as 'sysclose' system call argument.
  4140                              <1> 	; 	 (argument transfer method 1)
  4141                              <1> 
  4142                              <1> 	; / close the file
  4143                              <1> 	
  4144                              <1> 	;mov 	eax, ebx
  4145                              <1> 	; 04/12/2021
  4146                              <1> 	; ebx = file descriptor/number
  4147 000040E6 E83E070000          <1> 	call 	fclose
  4148                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  4149                              <1> 		; jsr r0,fclose / close the file
  4150                              <1>                	; br error2 / unknown file descriptor
  4151                              <1> 		; br sysret2
  4152                              <1> 	;; 14/05/2015
  4153                              <1> 	;jnc	sysret
  4154                              <1> 	; 04/12/2021
  4155 000040EB 7205                <1> 	jc	short sysclose_1
  4156 000040ED E9DAFAFFFF          <1> 	jmp	sysret
  4157                              <1> sysclose_1:
  4158 000040F2 C705[186F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  4158 000040FA 0000                <1>
  4159 000040FC E9ABFAFFFF          <1> 	jmp	error
  4160                              <1> 
  4161                              <1> 	; 19/12/2021
  4162                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4163                              <1> sysemt:
  4164                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4165                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4166                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  4167                              <1> 	;
  4168                              <1> 	; Retro UNIX 8086 v1 modification: 
  4169                              <1> 	;	'Enable Multi Tasking' system call instead 
  4170                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  4171                              <1> 	;
  4172                              <1> 	; Retro UNIX 8086 v1 feature only!
  4173                              <1> 	;	Using purpose: Kernel will start without time-out
  4174                              <1> 	;	(internal clock/timer) functionality.
  4175                              <1> 	;	Then etc/init will enable clock/timer for
  4176                              <1> 	;	multi tasking. (Then it will not be disabled again
  4177                              <1> 	;	except hardware reset/restart.)
  4178                              <1> 	;
  4179                              <1> 	
  4180                              <1> 	;cmp	byte [u.uid], 0 ; root ?
  4181                              <1> 	;;ja	error
  4182                              <1> 	;ja	badsys ; 14/05/2015
  4183                              <1> 	; 04/12/2021
  4184 00004101 66833D[F66E0000]00  <1> 	cmp	word [u.uid], 0 ; root ?
  4185 00004109 7605                <1> 	jna	short emt_0 
  4186 0000410B E94EFBFFFF          <1> 	jmp	badsys
  4187                              <1> emt_0:
  4188                              <1> 	; 19/12/2021
  4189                              <1> 	;cli
  4190 00004110 21DB                <1> 	and	ebx, ebx
  4191 00004112 740F                <1> 	jz	short emt_2
  4192                              <1> 	; Enable multi tasking -time sharing-
  4193 00004114 B8[124E0000]        <1> 	mov	eax, clock
  4194                              <1> emt_1:
  4195 00004119 A3[0F070000]        <1> 	mov	[x_timer], eax
  4196                              <1> 	;sti
  4197 0000411E E9A9FAFFFF          <1> 	jmp	sysret
  4198                              <1> emt_2:
  4199                              <1> 	; Disable multi tasking -time sharing-
  4200 00004123 B8[17070000]        <1> 	mov	eax, u_timer
  4201 00004128 EBEF                <1> 	jmp	short emt_1
  4202                              <1> 
  4203                              <1> 	; Original UNIX v1 'sysemt' routine
  4204                              <1> ;sysemt:
  4205                              <1>         ;
  4206                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  4207                              <1> 			 ; / in loc 30
  4208                              <1>         ;cmp    30,$core / was the argument a lower address 
  4209                              <1> 			; / than core
  4210                              <1>         ;blo    1f / yes, rtssym
  4211                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  4212                              <1> 			; / and less than "ecore"
  4213                              <1>         ;blo    2f / yes, sysret2
  4214                              <1> ;1:
  4215                              <1>         ;mov    $rtssym,30
  4216                              <1> ;2:
  4217                              <1>         ;br     sysret2
  4218                              <1> 
  4219                              <1> sysilgins:
  4220                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4221                              <1> 	; 03/06/2013
  4222                              <1> 	; Retro UNIX 8086 v1 modification: 
  4223                              <1> 	;	not a valid system call ! (not in use)
  4224                              <1> 	;
  4225 0000412A E92FFBFFFF          <1> 	jmp	badsys
  4226                              <1> 	;jmp	error
  4227                              <1> 	;;jmp 	sysret
  4228                              <1> 
  4229                              <1> 	; Original UNIX v1 'sysemt' routine
  4230                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  4231                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  4232                              <1> 			  ;/ put it in loc 8.,
  4233                              <1>         ;cmp    10,$core / making it the illegal instruction 
  4234                              <1> 		       ; / trap address
  4235                              <1>         ;blo    1f / is the address a user core address?  
  4236                              <1> 		; / yes, go to 2f
  4237                              <1>         ;cmp    10,$ecore
  4238                              <1>         ;blo    2f
  4239                              <1> ;1:
  4240                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  4241                              <1> 		    ; / instruction trap address for the system
  4242                              <1> ;2:
  4243                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  4244                              <1> 
  4245                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4246                              <1> sysmdate: ; < change the modification time of a file >
  4247                              <1> 	; 24/12/2021
  4248                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4249                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  4250                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4251                              <1> 	;
  4252                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  4253                              <1> 	; file into core. The user is checked if he is the owner 
  4254                              <1> 	; or super user. If he is neither an error occurs.
  4255                              <1> 	; 'setimod' is then called to set the i-node modification
  4256                              <1> 	; byte and the modification time, but the modification time
  4257                              <1> 	; is overwritten by whatever get put on the stack during
  4258                              <1> 	; a 'systime' system call. This calls are restricted to
  4259                              <1> 	; the super user.		
  4260                              <1> 	;
  4261                              <1> 	; Calling sequence:
  4262                              <1> 	;	sysmdate; name
  4263                              <1> 	; Arguments:
  4264                              <1> 	;	name - points to the name of file
  4265                              <1> 	; Inputs: (arguments)
  4266                              <1> 	; Outputs: -
  4267                              <1> 	; ...............................................................
  4268                              <1> 	;				
  4269                              <1> 	; Retro UNIX 8086 v1 modification: 
  4270                              <1> 	;	 The user/application program puts address 
  4271                              <1> 	;	 of the file name in BX register 
  4272                              <1> 	;	 as 'sysmdate' system call argument.
  4273                              <1> 	;
  4274                              <1> ; / change the modification time of a file
  4275                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  4276 0000412F 891D[C06E0000]      <1>         mov	[u.namep], ebx
  4277 00004135 E8A8070000          <1> 	call	namei
  4278                              <1> 		; jsr r0,namei / get its i-number
  4279                              <1> 	;;jc	error       
  4280                              <1> 	;	; br error2 / no, such file
  4281                              <1> 	;jc	fnotfound ; file not found !
  4282                              <1> 	; 24/12/2021
  4283 0000413A 7305                <1> 	jnc	short mdate_0
  4284 0000413C E9DFFEFFFF          <1> 	jmp	fnotfound
  4285                              <1> mdate_0: 
  4286 00004141 E82A110000          <1> 	call	iget
  4287                              <1> 		; jsr r0,iget / get i-node into core
  4288                              <1> 	;mov	al, [u.uid]
  4289                              <1> 	;cmp	al, [i.uid]
  4290                              <1>         ;	; cmpb u.uid,i.uid / is user same as owner
  4291                              <1> 	;je	short mdate_1
  4292                              <1>         ;	; beq 1f / yes
  4293                              <1> 	;and	al, al
  4294                              <1> 	;	; tstb u.uid / no, is user the super user
  4295                              <1> 	;;jnz	error
  4296                              <1> 	;	; bne error2 / no, error
  4297                              <1> 	;jz	short mdate_1
  4298                              <1> 	; 04/12/2021
  4299 00004146 66A1[F66E0000]      <1> 	mov	ax, [u.uid]
  4300 0000414C 663B05[446B0000]    <1> 	cmp	ax, [i.uid]
  4301 00004153 7414                <1> 	je	short mdate_1	
  4302 00004155 6621C0              <1> 	and	ax, ax
  4303 00004158 740F                <1> 	jz	short mdate_1
  4304                              <1> 
  4305 0000415A C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4305 00004162 0000                <1>
  4306 00004164 E943FAFFFF          <1> 	jmp	error
  4307                              <1> mdate_1: ;1:
  4308 00004169 E8A1120000          <1> 	call	setimod
  4309                              <1>         	; jsr r0,setimod / fill in modification data,
  4310                              <1> 		               ; / time etc.
  4311 0000416E BE[F06D0000]        <1> 	mov	esi, p_time
  4312 00004173 BF[786B0000]        <1> 	mov	edi, i.mtim
  4313 00004178 A5                  <1> 	movsd
  4314                              <1> 		; mov 4(sp),i.mtim / move present time to
  4315                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4316 00004179 E94EFAFFFF          <1>         jmp	sysret
  4317                              <1> 		; br sysret2
  4318                              <1> 
  4319                              <1> sysstty: ; < set tty status and mode >
  4320                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4321                              <1> 	;	    ((32 bit reg push/pop))
  4322                              <1> 	; 17/11/2015
  4323                              <1> 	; 12/11/2015
  4324                              <1> 	; 29/10/2015
  4325                              <1> 	; 17/10/2015
  4326                              <1> 	; 13/10/2015
  4327                              <1> 	; 29/06/2015
  4328                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4329                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4330                              <1> 	;
  4331                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4332                              <1> 	; whose file descriptor is in (u.r0).
  4333                              <1> 	;
  4334                              <1> 	; Calling sequence:
  4335                              <1> 	;	sysstty; arg
  4336                              <1> 	; Arguments:
  4337                              <1> 	;	arg - address of 3 consequitive words that contain
  4338                              <1> 	;	      the source of status data	
  4339                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4340                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4341                              <1> 	; ...............................................................
  4342                              <1> 	;	
  4343                              <1> 	; Retro UNIX 8086 v1 modification: 
  4344                              <1> 	;	'sysstty' system call will set the tty
  4345                              <1> 	;	(clear keyboard buffer and set cursor position)
  4346                              <1> 	;	 in following manner:
  4347                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4348                              <1> 	;
  4349                              <1> 	; Inputs:
  4350                              <1> 	;	BX = 0 --> means
  4351                              <1> 	;	   If CL = FFh
  4352                              <1> 	;	      set cursor position for console tty, only 
  4353                              <1> 	;	      CH will be ignored (char. will not be written)	
  4354                              <1> 	;	   If CH = 0 (CL < FFh)
  4355                              <1> 	;	      set console tty for (current) process
  4356                              <1> 	;	      CL = tty number (0 to 9)
  4357                              <1> 	;	      (If CH = 0, character will not be written)			
  4358                              <1> 	;          If CH > 0 (CL < FFh)	
  4359                              <1> 	;             CL = tty number (0 to 9)
  4360                              <1> 	;	      CH = character will be written
  4361                              <1> 	;	        at requested cursor position (in DX)	
  4362                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4363                              <1>   	;		(only tty number 0 to 7) 
  4364                              <1> 	;          DL = communication parameters (for serial ports) 
  4365                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4366                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4367                              <1> 	;			or set cursor position	
  4368                              <1> 	;	   DH = 0FFh -> DL is not valid
  4369                              <1> 	;		do not set serial port parameters 
  4370                              <1> 	;		or do not set cursor position
  4371                              <1> 	;
  4372                              <1> 	;	BX > 0 --> points to name of tty
  4373                              <1> 	;    	   CH > 0 -->
  4374                              <1> 	;		CH = character will be written in current 
  4375                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4376                              <1> 	;	     	or character will be sent to serial port
  4377                              <1> 	;	     	(for tty number 8 or 9)
  4378                              <1> 	;		CL = color of the character if tty number < 8.
  4379                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4380                              <1> 	;		set mode (tty 8 to 9) or 
  4381                              <1> 	;		set current cursor positions (tty 0 to 7) only. 
  4382                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4383                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4384                              <1> 	;		(DL is not valid)
  4385                              <1> 	;	   DL = communication parameters 
  4386                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4387                              <1> 	; Outputs:
  4388                              <1> 	;	cf = 0 -> OK
  4389                              <1> 	;	     AL = tty number (0 to 9)
  4390                              <1> 	;	     AH = line status if tty number is 8 or 9
  4391                              <1> 	;	     AH = process number (of the caller) 	
  4392                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4393                              <1> 	;	     AH = FFh if the tty is locked 
  4394                              <1> 	;		  (owned by another process)
  4395                              <1> 	;	        = process number (of the caller) 
  4396                              <1> 	;		  (if < FFh and tty number < 8)
  4397                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4398                              <1> 	;	     AH = line status if tty number is 8 or 9
  4399                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4400                              <1> 	;
  4401                              <1> 	; 27/06/2015 (32 bit modifications)
  4402                              <1> 	; 14/01/2014
  4403 0000417E 31C0                <1> 	xor 	eax, eax
  4404 00004180 6648                <1> 	dec	ax ; 17/10/2015
  4405 00004182 A3[A46E0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4406 00004187 21DB                <1> 	and	ebx, ebx
  4407                              <1>         ;jnz	sysstty_6
  4408                              <1> 	; 24/12/2021
  4409 00004189 7405                <1> 	jz	short sysstty_14
  4410 0000418B E9C7000000          <1> 	jmp	sysstty_6
  4411                              <1> sysstty_14:
  4412                              <1> 	; set console tty
  4413                              <1> 	; 29/10/2015
  4414                              <1> 	; 17/01/2014 
  4415 00004190 80F909              <1> 	cmp	cl, 9
  4416 00004193 7613                <1> 	jna	short sysstty_0
  4417                              <1> 	; 17/11/2015
  4418 00004195 80F9FF              <1> 	cmp	cl, 0FFh
  4419 00004198 7202                <1> 	jb	short sysstty_13
  4420 0000419A 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4421                              <1> sysstty_13:
  4422 0000419C 8A1D[F56E0000]      <1> 	mov	bl, [u.uno] ; process number
  4423 000041A2 8A8B[DF6B0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4424                              <1> sysstty_0:
  4425                              <1> 	; 29/06/2015
  4426 000041A8 52                  <1> 	push	edx ; 24/12/2021
  4427 000041A9 51                  <1> 	push	ecx
  4428 000041AA 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4429 000041AC 88C8                <1> 	mov	al, cl
  4430 000041AE A2[A46E0000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4431 000041B3 E8A81A0000          <1> 	call	ottyp
  4432 000041B8 59                  <1> 	pop	ecx
  4433 000041B9 5A                  <1> 	pop	edx
  4434                              <1> 	;
  4435 000041BA 7256                <1> 	jc	short sysstty_pd_err
  4436                              <1> 	;
  4437 000041BC 80F908              <1> 	cmp	cl, 8
  4438 000041BF 7220                <1> 	jb	short sysstty_2
  4439                              <1> 	;
  4440 000041C1 80FEFF              <1> 	cmp	dh, 0FFh
  4441 000041C4 741B                <1> 	je	short sysstty_2
  4442                              <1> 	; set communication parameters for serial ports
  4443                              <1> 	; 29/10/2015
  4444 000041C6 88D4                <1> 	mov	ah, dl ; communication parameters
  4445                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4446                              <1> 		;			 THRE int + RDA int 
  4447                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4448                              <1> 		;			 THRE int + RDA int 
  4449 000041C8 28C0                <1> 	sub	al, al ; 0
  4450                              <1> 	; 12/07/2014
  4451 000041CA 80F909              <1> 	cmp	cl, 9
  4452 000041CD 7202                <1> 	jb	short sysstty_1
  4453 000041CF FEC0                <1> 	inc	al
  4454                              <1> sysstty_1:
  4455 000041D1 51                  <1> 	push	ecx ; 24/12/2021
  4456                              <1> 	; 29/06/2015	
  4457 000041D2 E85FF4FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4458 000041D7 66890D[A56E0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4459                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4460 000041DE 59                  <1> 	pop	ecx
  4461 000041DF 7267                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4462                              <1> sysstty_2:
  4463                              <1> 	; 17/01/2014
  4464 000041E1 20ED                <1> 	and	ch, ch 	; set cursor position 
  4465                              <1> 			; or comm. parameters ONLY
  4466 000041E3 750D                <1> 	jnz	short sysstty_3
  4467 000041E5 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4468 000041EC 888B[DF6B0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4469                              <1> sysstty_3:
  4470                              <1> 	; 16/01/2014
  4471 000041F2 88E8                <1> 	mov	al, ch ; character  ; 0 to FFh
  4472                              <1> 	; 17/11/2015
  4473 000041F4 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4474 000041F6 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4475                              <1>         ;jna	sysstty_9
  4476                              <1> 	; 24/12/2021
  4477 000041F8 7705                <1> 	ja	short sysstty_12
  4478 000041FA E9BE000000          <1> 	jmp	sysstty_9
  4479                              <1> sysstty_12:
  4480                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4481                              <1> 	; (Set specified serial port as console tty port)
  4482                              <1> 	; CH = character to be written
  4483                              <1> 	; 15/04/2014
  4484                              <1> 	; CH = 0 --> initialization only
  4485                              <1> 	; AL = character
  4486                              <1> 	; 26/06/2014
  4487 000041FF 880D[D96E0000]      <1> 	mov	[u.ttyn], cl
  4488                              <1> 	; 12/07/2014
  4489 00004205 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4490 00004207 20C0                <1> 	and	al, al
  4491 00004209 7416                <1> 	jz	short sysstty_4 ; al = ch = 0
  4492                              <1>  	; 04/07/2014
  4493 0000420B E893200000          <1> 	call 	sndc
  4494                              <1> 	; 12/07/2014
  4495 00004210 EB1B                <1> 	jmp	short sysstty_5
  4496                              <1> sysstty_pd_err: ; 29/06/2015
  4497                              <1> 	; 'permission denied !' error
  4498 00004212 C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4498 0000421A 0000                <1>
  4499 0000421C E98BF9FFFF          <1> 	jmp	error
  4500                              <1> sysstty_4:
  4501                              <1> 	; 12/07/2014
  4502                              <1> 	;xchg 	ah, al	; al = 0 -> al = ah, ah = 0
  4503 00004221 88E0                <1> 	mov	al, ah ; 29/06/2015
  4504 00004223 2C08                <1> 	sub	al, 8
  4505                              <1> 	; 27/06/2015
  4506 00004225 E804F4FFFF          <1> 	call	sp_status ; get serial port status
  4507                              <1> 	; AL = Line status, AH = Modem status
  4508                              <1> 	; 12/11/2015
  4509 0000422A 3C80                <1> 	cmp	al, 80h
  4510 0000422C F5                  <1> 	cmc
  4511                              <1> sysstty_5:
  4512 0000422D 66A3[A56E0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4513                              <1> 		     ; EAX bits 16-23 = modem status	
  4514 00004233 9C                  <1> 	pushf
  4515 00004234 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4516 00004236 A0[D96E0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4517 0000423B E8421B0000          <1> 	call	cttyp
  4518 00004240 9D                  <1> 	popf
  4519                              <1> 	;jnc	sysret	
  4520                              <1> 	; 24/12/2021
  4521 00004241 7205                <1> 	jc	short sysstty_tmout_err
  4522 00004243 E984F9FFFF          <1> 	jmp	sysret
  4523                              <1> 	; time out error 
  4524                              <1> sysstty_tmout_err:
  4525 00004248 C705[186F0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4525 00004250 0000                <1>
  4526 00004252 E955F9FFFF          <1> 	jmp	error
  4527                              <1> sysstty_6:
  4528 00004257 52                  <1> 	push	edx ; 24/12/2021
  4529 00004258 51                  <1> 	push	ecx
  4530 00004259 891D[C06E0000]      <1> 	mov	[u.namep], ebx
  4531 0000425F E87E060000          <1> 	call	namei
  4532 00004264 59                  <1> 	pop	ecx
  4533 00004265 5A                  <1> 	pop	edx
  4534 00004266 720E                <1> 	jc	short sysstty_inv_dn
  4535                              <1> 	;
  4536 00004268 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4537 0000426C 7708                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4538                              <1> 	;
  4539 0000426E 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4540                              <1> 		       ; /dev/COM1, /dev/COM2
  4541 00004270 7213                <1> 	jb	short sysstty_7
  4542 00004272 2C0A                <1> 	sub	al, 10
  4543 00004274 EB20                <1> 	jmp	short sysstty_8
  4544                              <1> sysstty_inv_dn: 
  4545                              <1> 	; 27/06/2015
  4546                              <1> 	; Invalid device name (not a tty) ! error
  4547                              <1> 	; (Device is not a tty or device name not found)
  4548 00004276 C705[186F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4548 0000427E 0000                <1>
  4549 00004280 E927F9FFFF          <1> 	jmp	error 
  4550                              <1> sysstty_7:
  4551 00004285 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4552 00004287 75ED                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4553 00004289 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4554 00004290 8A83[DF6B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4555                              <1> sysstty_8:	
  4556 00004296 A2[A46E0000]        <1> 	mov	[u.r0], al
  4557 0000429B 52                  <1> 	push	edx ; 24/12/2021
  4558 0000429C 50                  <1> 	push	eax
  4559 0000429D 51                  <1> 	push	ecx	
  4560 0000429E E8BD190000          <1> 	call	ottyp
  4561 000042A3 59                  <1> 	pop	ecx
  4562 000042A4 58                  <1> 	pop	eax
  4563 000042A5 5A                  <1> 	pop	edx
  4564                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4565                              <1> 	; 24/12/2021
  4566 000042A6 7305                <1> 	jnc	short sysstty_15
  4567                              <1> 	; 'permission denied !'
  4568 000042A8 E965FFFFFF          <1> 	jmp	sysstty_pd_err
  4569                              <1> sysstty_15:
  4570                              <1> 	; 29/10/2015
  4571 000042AD 86E9                <1> 	xchg 	ch, cl
  4572                              <1> 		; cl = character, ch = color code
  4573 000042AF 86C1                <1> 	xchg	al, cl
  4574                              <1> 		; al = character, cl = tty number
  4575 000042B1 80F907              <1> 	cmp	cl, 7
  4576                              <1> 	;ja	sysstty_12
  4577                              <1> 	; 24/12/2021
  4578 000042B4 7605                <1> 	jna	short sysstty_16
  4579 000042B6 E944FFFFFF          <1> 	jmp	sysstty_12
  4580                              <1> sysstty_16:
  4581                              <1> 	; 16/01/2014
  4582 000042BB 30FF                <1> 	xor	bh, bh
  4583                              <1> 	;
  4584                              <1> sysstty_9: 	; tty 0 to tty 7
  4585                              <1> 	; al = character
  4586 000042BD 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4587 000042C0 740B                <1> 	je	short sysstty_10
  4588 000042C2 51                  <1> 	push	ecx ; 24/12/2021
  4589 000042C3 50                  <1> 	push	eax	
  4590                              <1> 	;movzx, ebx, cl
  4591 000042C4 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4592 000042C6 E813D2FFFF          <1> 	call	set_cpos
  4593 000042CB 58                  <1> 	pop	eax
  4594 000042CC 59                  <1> 	pop	ecx
  4595                              <1> sysstty_10: 
  4596                              <1> 	; 29/10/2015
  4597 000042CD 08C0                <1> 	or	al, al ; character
  4598 000042CF 740D                <1> 	jz      short sysstty_11 ; al = 0
  4599                              <1> 	; 17/11/2015
  4600 000042D1 3CFF                <1> 	cmp	al, 0FFh
  4601 000042D3 7309                <1> 	jnb	short sysstty_11
  4602                              <1> 		; ch > 0 and ch < FFh
  4603                              <1> 	; write a character at current cursor position
  4604 000042D5 88EC                <1> 	mov	ah, ch ; color/attribute
  4605                              <1> 	; 12/07/2014
  4606 000042D7 51                  <1> 	push	ecx ; 24/12/2021
  4607 000042D8 E83FD3FFFF          <1> 	call	write_c_current
  4608 000042DD 59                  <1> 	pop	ecx
  4609                              <1> sysstty_11:
  4610                              <1> 	; 14/01/2014
  4611 000042DE 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4612                              <1> 	; 18/01/2014
  4613                              <1> 	;movzx	eax, cl ; 27/06/2015
  4614 000042E0 88C8                <1> 	mov	al, cl
  4615 000042E2 E89B1A0000          <1> 	call	cttyp
  4616 000042E7 E9E0F8FFFF          <1> 	jmp	sysret
  4617                              <1> 
  4618                              <1> ; Original UNIX v1 'sysstty' routine:
  4619                              <1> ; gtty:
  4620                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4621                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4622                              <1> 	; 		/ r2 has source
  4623                              <1>         ;mov    r2,-(sp)
  4624                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4625                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4626                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4627                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4628                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4629                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4630                              <1>         ;       br .+4 / list empty, skip branch
  4631                              <1>         ;br     1b / get another character until list is empty
  4632                              <1>         ;mov    0b,r1 / move cc offset to r1
  4633                              <1>         ;inc    r1 / bump it for output clist
  4634                              <1>         ;tstb   cc(r1) / is it 0
  4635                              <1>         ;beq    1f / yes, no characters to output
  4636                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4637                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4638                              <1>         ;br     1b / try to calm it down again
  4639                              <1> ;1:
  4640                              <1>         ;mov    (sp)+,r1
  4641                              <1>         ;mov    (sp)+,r2 / restore registers
  4642                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4643                              <1>         ;beq    1f / if 0, 1f
  4644                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4645                              <1>         ;                   / control status register
  4646                              <1> ;1:
  4647                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4648                              <1>         ;beq    1f / if 0 1f
  4649                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4650                              <1> 	;		    / control status reg
  4651                              <1> ;1:
  4652                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4653                              <1>         ;jmp     sysret2 / return to user
  4654                              <1> 
  4655                              <1> sysgtty: ; < get tty status >
  4656                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4657                              <1> 	;	    ((32 bit reg push/pop))
  4658                              <1> 	; 23/11/2015
  4659                              <1> 	; 29/10/2015
  4660                              <1> 	; 17/10/2015
  4661                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4662                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4663                              <1> 	;
  4664                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4665                              <1> 	; It stores in the three words addressed by it's argument
  4666                              <1> 	; the status of the typewriter whose file descriptor
  4667                              <1> 	; in (u.r0).
  4668                              <1> 	;
  4669                              <1> 	; Calling sequence:
  4670                              <1> 	;	sysgtty; arg
  4671                              <1> 	; Arguments:
  4672                              <1> 	;	arg - address of 3 words destination of the status
  4673                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4674                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4675                              <1> 	; ...............................................................
  4676                              <1> 	;	
  4677                              <1> 	; Retro UNIX 8086 v1 modification: 
  4678                              <1> 	;	'sysgtty' system call will return status of tty
  4679                              <1> 	;	(keyboard, serial port and video page status)
  4680                              <1> 	;	 in following manner:
  4681                              <1> 	;
  4682                              <1> 	; Inputs:
  4683                              <1> 	;	BX = 0 --> means 
  4684                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4685                              <1> 	;	                 for (current) process
  4686                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4687                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4688                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4689                              <1> 	;	     CH > 0 -->	tty number + 1
  4690                              <1> 	;
  4691                              <1> 	;	BX > 0 --> points to name of tty
  4692                              <1> 	;	     CL = 0 --> return keyboard status
  4693                              <1> 	;	     CL = 1 --> return video page status
  4694                              <1> 	;	     CH = undefined		 
  4695                              <1> 	;
  4696                              <1> 	; Outputs:
  4697                              <1> 	;	cf = 0 ->
  4698                              <1> 	;
  4699                              <1> 	;	     AL = tty number from 0 to 9
  4700                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4701                              <1> 	;	     AH = 0 if the tty is free/unused
  4702                              <1> 	;	     AH = the process number of the caller 
  4703                              <1>  	;	     AH = FFh if the tty is locked by another process
  4704                              <1> 	;
  4705                              <1> 	;	  (if calling is for serial port status)
  4706                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4707                              <1> 	;		  (BH = modem status, BL = Line status)
  4708                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4709                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4710                              <1> 	;
  4711                              <1> 	;	  (if calling is for keyboard status)
  4712                              <1> 	;	     BX = current character in tty/keyboard buffer
  4713                              <1> 	;		  (BH = scan code, BL = ascii code)
  4714                              <1> 	;		  (BX=0 if there is not a waiting character)
  4715                              <1> 	;	     CX  is undefined
  4716                              <1> 	;
  4717                              <1> 	;	  (if calling is for video page status)	
  4718                              <1> 	;	     BX = cursor position on the video page
  4719                              <1> 	;		  if tty number < 8
  4720                              <1> 	;		  (BH = row, BL = column)
  4721                              <1> 	;	     CX = current character (in cursor position)
  4722                              <1> 	;		  on the video page of the tty 
  4723                              <1> 	;		  if tty number < 8
  4724                              <1> 	;		  (CH = color, CL = character)
  4725                              <1> 	;	
  4726                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4727                              <1> 	;
  4728                              <1> 	;	     AH = FFh if the caller is not owner of
  4729                              <1> 	;		  specified tty or console tty
  4730                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4731                              <1> 	;	     BX, CX are undefined if cf = 1
  4732                              <1> 	;
  4733                              <1> 	;	  (If tty number is 8 or 9)
  4734                              <1> 	;	     AL = tty number 
  4735                              <1> 	;	     AH = the process number of the caller 
  4736                              <1> 	;	     BX = serial port status
  4737                              <1> 	;  		 (BH = modem status, BL = Line status)
  4738                              <1> 	;	     CX = 0
  4739                              <1> 	;
  4740                              <1> 		
  4741                              <1> gtty:   ; get (requested) tty number
  4742                              <1> 	; 17/10/2015
  4743                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4744                              <1> 	; 30/05/2013 - 12/07/2014
  4745                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4746                              <1> 	;
  4747                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4748                              <1> 	;
  4749                              <1> 	; 28/06/2015 (32 bit modifications)
  4750                              <1> 	; 16/01/2014
  4751 000042EC 31C0                <1> 	xor 	eax, eax
  4752 000042EE 6648                <1> 	dec	ax ; 17/10/2015
  4753 000042F0 A3[A46E0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4754 000042F5 80F901              <1> 	cmp	cl, 1
  4755 000042F8 760F                <1> 	jna	short sysgtty_0
  4756                              <1> sysgtty_invp:
  4757                              <1> 	; 28/06/2015
  4758 000042FA C705[186F0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4758 00004302 0000                <1>
  4759 00004304 E9A3F8FFFF          <1> 	jmp	error
  4760                              <1> sysgtty_0:	
  4761 00004309 21DB                <1> 	and	ebx, ebx
  4762 0000430B 742E                <1> 	jz	short sysgtty_1
  4763                              <1> 	;
  4764 0000430D 891D[C06E0000]      <1> 	mov	[u.namep], ebx
  4765                              <1> 	;push	cx ; 23/11/2015
  4766 00004313 51                  <1> 	push	ecx ; 24/12/2021
  4767 00004314 E8C9050000          <1> 	call	namei
  4768 00004319 59                  <1> 	pop	ecx
  4769                              <1> 	;pop	cx ; 23/11/2015
  4770 0000431A 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4771                              <1> 	;
  4772 0000431C 6683F801            <1> 	cmp	ax, 1
  4773 00004320 7622                <1> 	jna	short sysgtty_2
  4774 00004322 6683E80A            <1> 	sub	ax, 10
  4775 00004326 6683F809            <1> 	cmp	ax, 9
  4776                              <1> 	;ja	short sysgtty_inv_dn
  4777                              <1> 	;mov	ch, al
  4778                              <1> 	;jmp	short sysgtty_4
  4779                              <1> 	; 23/11/2015
  4780 0000432A 7629                <1> 	jna	short sysgtty_4
  4781                              <1> sysgtty_inv_dn: 
  4782                              <1> 	; 28/06/2015
  4783                              <1> 	; Invalid device name (not a tty) ! error
  4784                              <1> 	; (Device is not a tty or device name not found)
  4785 0000432C C705[186F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4785 00004334 0000                <1>
  4786 00004336 E971F8FFFF          <1> 	jmp	error 
  4787                              <1> sysgtty_1:
  4788                              <1> 	; 16/01/2014
  4789 0000433B 80FD0A              <1> 	cmp	ch, 10
  4790 0000433E 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4791 00004340 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4792 00004342 790F                <1> 	jns	short sysgtty_3 ; not negative
  4793                              <1> 	;
  4794                              <1> sysgtty_2:
  4795                              <1> 	; get tty number of console tty
  4796 00004344 8A25[F56E0000]      <1> 	mov	ah, [u.uno]
  4797                              <1>  	; 28/06/2015
  4798 0000434A 0FB6DC              <1> 	movzx 	ebx, ah
  4799 0000434D 8AAB[DF6B0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4800                              <1> sysgtty_3:
  4801 00004353 88E8                <1> 	mov	al, ch
  4802                              <1> sysgtty_4:
  4803 00004355 A2[A46E0000]        <1> 	mov	[u.r0], al
  4804                              <1>  	; 28/06/2015
  4805                              <1> 	;cmp	al, 9
  4806                              <1> 	;ja	short sysgtty_invp
  4807 0000435A 8B2D[A06E0000]      <1> 	mov	ebp, [u.usp]
  4808                              <1> 	; 23/11/2015
  4809 00004360 20C9                <1> 	and	cl, cl
  4810 00004362 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4811 00004364 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4812 00004366 722E                <1> 	jb	short sysgtty_6 ; video page status
  4813                              <1> 	; serial port status
  4814                              <1> 	; 12/07/2014
  4815                              <1> 	;mov	dx, 0
  4816                              <1> 	;je	short sysgtty_5
  4817                              <1> 	;inc	dl
  4818                              <1> ;sysgtty_5:
  4819                              <1> 	; 28/06/2015
  4820 00004368 2C08                <1> 	sub	al, 8
  4821 0000436A E8BFF2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4822                              <1> 	; AL = Line status, AH = Modem status
  4823 0000436F 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4824 00004373 8A25[F56E0000]      <1> 	mov	ah, [u.uno]
  4825 00004379 8825[A56E0000]      <1>         mov     [u.r0+1], ah
  4826                              <1> 	; 24/12/2021
  4827 0000437F 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4828                              <1> 				; (in ECX)
  4829 00004385 A880                <1> 	test	al, 80h
  4830 00004387 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4831 00004389 A801                <1> 	test	al, 1
  4832                              <1> 	;jz	sysret
  4833 0000438B 7404                <1> 	jz	short sysgtty_10
  4834 0000438D 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4835                              <1> sysgtty_10:
  4836 00004391 E936F8FFFF          <1> 	jmp	sysret
  4837                              <1> sysgtty_6:
  4838 00004396 A2[D96E0000]        <1> 	mov	[u.ttyn], al ; tty number
  4839                              <1> 	;movzx	ebx, al
  4840 0000439B 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4841 0000439D D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4842                              <1> 	; 22/04/2014 - 29/06/2015
  4843 0000439F 81C3[F46D0000]      <1>         add     ebx, ttyl
  4844 000043A5 8A23                <1>  	mov	ah, [ebx]
  4845 000043A7 3A25[F56E0000]      <1> 	cmp	ah, [u.uno]
  4846 000043AD 7404                <1> 	je	short sysgtty_7
  4847 000043AF 20E4                <1> 	and	ah, ah
  4848                              <1> 	;jz	short sysgtty_7
  4849 000043B1 7506                <1> 	jnz	short sysgtty_8
  4850                              <1> 	;mov	ah, 0FFh
  4851                              <1> sysgtty_7:
  4852 000043B3 8825[A56E0000]      <1>         mov     [u.r0+1], ah
  4853                              <1> sysgtty_8:
  4854 000043B9 08C9                <1> 	or	cl, cl
  4855 000043BB 7510                <1> 	jnz	short sysgtty_9
  4856 000043BD B001                <1> 	mov	al, 1  ; test a key is available
  4857 000043BF E8621E0000          <1> 	call	getc
  4858 000043C4 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4859 000043C8 E9FFF7FFFF          <1> 	jmp	sysret
  4860                              <1> sysgtty_9:
  4861 000043CD 8A1D[D96E0000]      <1> 	mov	bl, [u.ttyn]
  4862                              <1> 	; bl = video page number
  4863 000043D3 E8C11F0000          <1> 	call 	get_cpos
  4864                              <1> 	; dx = cursor position
  4865 000043D8 66895510            <1> 	mov	[ebp+16], dx ; bx
  4866                              <1> 	;mov	bl, [u.ttyn]
  4867                              <1> 	; bl = video page number
  4868 000043DC E8C91F0000          <1> 	call	read_ac_current
  4869                              <1> 	; ax = character and attribute/color
  4870 000043E1 66894518            <1> 	mov	[ebp+24], ax ; cx
  4871 000043E5 E9E2F7FFFF          <1> 	jmp	sysret
  4872                              <1> sysgtty_dnr_err:
  4873                              <1> 	; 'device not responding !' error	
  4874                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4875 000043EA C705[186F0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4875 000043F2 0000                <1>
  4876 000043F4 E9B3F7FFFF          <1> 	jmp	error	
  4877                              <1> 
  4878                              <1> ; Original UNIX v1 'sysgtty' routine:
  4879                              <1> ; sysgtty:
  4880                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4881                              <1> 	;	       / r2 has destination
  4882                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4883                              <1> 	;                     / in 1st word of dest
  4884                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4885                              <1> 	;                     / in 2nd word of dest
  4886                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4887                              <1>         ;jmp    sysret2 / return to user
  4888                              <1> 	
  4889                              <1> ; Original UNIX v1 'gtty' routine:
  4890                              <1> ; gtty:
  4891                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4892                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4893                              <1>         ;jsr    r0,getf / get the i-number of the file
  4894                              <1>         ;tst    r1 / is it open for reading
  4895                              <1>         ;bgt    1f / yes
  4896                              <1>         ;neg    r1 / no, i-number is negative, 
  4897                              <1> 	;          / so make it positive
  4898                              <1> ;1:
  4899                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4900                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4901                              <1>         ;bhis   error9 / no, error
  4902                              <1>         ;asl    r1 / 0%2
  4903                              <1>         ;asl    r1 / 0%4 / yes
  4904                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4905                              <1> 	;	       ; / tty block
  4906                              <1>         ;mov    u.off,r2 / put argument in r2
  4907                              <1>         ;rts    r0 / return
  2077                                  %include 'u2.s'      ; 11/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) - SYS2.INC
  2082                              <1> ; Last Modification: 10/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 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2093                              <1> ;
  2094                              <1> ; ****************************************************************************
  2095                              <1> 
  2096                              <1> ; temporary - 01/01/2022
  2097                              <1> %if 0
  2098                              <1> 
  2099                              <1> syslink:
  2100                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2101                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2102                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2103                              <1> 	;
  2104                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2105                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2106                              <1> 	; given to the entry that will go in the current directory.
  2107                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2108                              <1> 	; in the name 2 entry of current directory is the same
  2109                              <1> 	; i-number for the name 1 file.
  2110                              <1> 	;
  2111                              <1> 	; Calling sequence:
  2112                              <1> 	;	syslink; name 1; name 2
  2113                              <1> 	; Arguments:
  2114                              <1> 	;	name 1 - file name to which link will be created.
  2115                              <1> 	;	name 2 - name of entry in current directory that
  2116                              <1> 	;		 links to name 1.
  2117                              <1> 	; Inputs: -
  2118                              <1> 	; Outputs: -
  2119                              <1> 	; ...............................................................
  2120                              <1> 	;	
  2121                              <1> 	; Retro UNIX 8086 v1 modification: 
  2122                              <1> 	;       'syslink' system call has two arguments; so,
  2123                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2124                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2125                              <1> 	;
  2126                              <1> 		; / name1, name2
  2127                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2128                              <1> 	mov	[u.namep], ebx
  2129                              <1> 	push	ecx
  2130                              <1> 	call	namei
  2131                              <1> 		; jsr r0,namei / find the i-number associated with
  2132                              <1> 			     ; / the 1st path name
  2133                              <1>      	;;and	ax, ax
  2134                              <1> 	;;jz	error ; File not found
  2135                              <1> 	;jc	error 
  2136                              <1> 		; br error9 / cannot be found
  2137                              <1> 	jnc	short syslink0
  2138                              <1> 	;pop 	ecx
  2139                              <1> 	; 'file not found !' error
  2140                              <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2141                              <1> 	jmp	error
  2142                              <1> syslink0:
  2143                              <1> 	call	iget
  2144                              <1> 		; jsr r0,iget / get the i-node into core
  2145                              <1> 	pop	dword [u.namep] ; ecx
  2146                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2147                              <1> 	; 24/12/2021
  2148                              <1> 	push	eax ; *
  2149                              <1> 	;push	ax
  2150                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2151                              <1> 			    ; / (a link to this file is to be created)
  2152                              <1> 	; 24/12/2021
  2153                              <1> 	mov	cl, [cdev]
  2154                              <1> 	push	ecx ; **
  2155                              <1> 	;push	word [cdev]
  2156                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2157                              <1> 	call	isdir
  2158                              <1> 		; jsr r0,isdir / is it a directory
  2159                              <1> 	call	namei
  2160                              <1> 		; jsr r0,namei / no, get i-number of name2
  2161                              <1> 	;jnc	error
  2162                              <1> 		; br .+4   / not found 
  2163                              <1> 			 ; / so r1 = i-number of current directory
  2164                              <1> 			 ; / ii = i-number of current directory
  2165                              <1> 		; br error9 / file already exists., error
  2166                              <1> 	jc	short syslink1
  2167                              <1> 	; pop eax ; 24/12/2021
  2168                              <1> 	; pop eax
  2169                              <1> 	; 'file exists !' error
  2170                              <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2171                              <1> 	jmp	error
  2172                              <1> syslink1:
  2173                              <1> 	;pop	cx
  2174                              <1> 	; 24/12/2021
  2175                              <1> 	pop	ecx ; **
  2176                              <1> 	;cmp	cx, [cdev]
  2177                              <1> 	cmp	cl, [cdev]
  2178                              <1> 	;jne	error
  2179                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2180                              <1> 			       ; / end of current directory
  2181                              <1> 	        ; bne error9
  2182                              <1> 	je	short syslink2
  2183                              <1> 	; 'not same drive !' error
  2184                              <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2185                              <1> 	jmp	error
  2186                              <1> syslink2:
  2187                              <1> 	;pop	eax ; 24/12/2021
  2188                              <1> 	;push	eax
  2189                              <1> 	; 24/12/2021
  2190                              <1> 	mov	eax, [esp] ; *
  2191                              <1> 	mov	[u.dirbuf], ax
  2192                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2193                              <1> 	call	mkdir
  2194                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2195                              <1> 		 	     ; / in current directory
  2196                              <1> 	; 24/12/2021
  2197                              <1> 	pop	eax ; *
  2198                              <1> 	;pop	ax
  2199                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2200                              <1> 	call	iget
  2201                              <1> 		; jsr r0,iget / get i-node into core
  2202                              <1> 	inc	byte [i.nlks]
  2203                              <1> 		; incb i.nlks / add 1 to its number of links
  2204                              <1> 	call	setimod
  2205                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2206                              <1> 	jmp	sysret
  2207                              <1> 
  2208                              <1> isdir:
  2209                              <1> 	; 08/01/2022
  2210                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  2211                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2212                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2213                              <1> 	;
  2214                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2215                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2216                              <1> 	;  called by syslink and sysunlink to make sure directories
  2217                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2218                              <1> 	; 'isdir' does not bother checking. The current i-node
  2219                              <1> 	;  is not disturbed.			
  2220                              <1> 	;		
  2221                              <1> 	; INPUTS ->
  2222                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2223                              <1> 	;    u.uid - user id
  2224                              <1> 	; OUTPUTS ->
  2225                              <1> 	;    r1 - contains current i-number upon exit
  2226                              <1> 	;    	 (current i-node back in core) 
  2227                              <1> 	;	
  2228                              <1> 	; ((AX = R1))
  2229                              <1> 	;
  2230                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2231                              <1> 	;
  2232                              <1> 
  2233                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2234                              <1> 	; / there is an error unless super user made the call
  2235                              <1> 	
  2236                              <1> 	; 01/01/2022
  2237                              <1> 	cmp	word [u.uid], 0 ; 16 bit uid (runix v2 fs inode)
  2238                              <1> 	;cmp	byte [u.uid], 0 
  2239                              <1> 		; tstb u.uid / super user
  2240                              <1> 	jna	short isdir1
  2241                              <1> 		; beq 1f / yes, don't care
  2242                              <1> 	; 08/01/2022
  2243                              <1> 	push	dword [ii]
  2244                              <1> 	;push	word [ii]
  2245                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2246                              <1> 	call	iget
  2247                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2248                              <1> 	; 01/01/2022 (runix v2 fs inode flag)
  2249                              <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  2250                              <1> 	jz	short isdir2 ; no, error!
  2251                              <1> 	test	byte [i.flgs+1], 40h ; directory flag
  2252                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2253                              <1> 		; bit $40000,i.flgs / is it a directory
  2254                              <1> 	;jnz	error
  2255                              <1> 		; bne error9 / yes, error
  2256                              <1> 	jz	short isdir0
  2257                              <1> isdir2:
  2258                              <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2259                              <1> 				; 'permission denied !' error
  2260                              <1> 	;pop	ax
  2261                              <1> 	jmp	error	
  2262                              <1> isdir0:	
  2263                              <1> 	; 08/01/2022
  2264                              <1> 	pop	eax
  2265                              <1> 	;pop	ax
  2266                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2267                              <1> 	call	iget
  2268                              <1> 		; jsr r0,iget / get it back in
  2269                              <1> isdir1: ; 1:
  2270                              <1> 	retn
  2271                              <1> 		; rts r0
  2272                              <1> 
  2273                              <1> sysunlink:
  2274                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2275                              <1> 	; 04/12/2015 (14 byte file names)
  2276                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2277                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2278                              <1> 	;
  2279                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2280                              <1> 	; name from its directory. If this entry was the last link
  2281                              <1> 	; to the file, the contents of the file are freed and the
  2282                              <1> 	; file is destroyed. If, however, the file was open in any
  2283                              <1> 	; process, the actual destruction is delayed until it is 
  2284                              <1> 	; closed, even though the directory entry has disappeared.
  2285                              <1> 	; 
  2286                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2287                              <1> 	; does not exist or that its directory can not be written.
  2288                              <1> 	; Write permission is not required on the file itself.
  2289                              <1> 	; It is also illegal to unlink a directory (except for
  2290                              <1> 	; the superuser).
  2291                              <1> 	;
  2292                              <1> 	; Calling sequence:
  2293                              <1> 	;	sysunlink; name
  2294                              <1> 	; Arguments:
  2295                              <1> 	;	name - name of directory entry to be removed 
  2296                              <1> 	; Inputs: -
  2297                              <1> 	; Outputs: -
  2298                              <1> 	; ...............................................................
  2299                              <1> 	;				
  2300                              <1> 	; Retro UNIX 8086 v1 modification:
  2301                              <1> 	;	 The user/application program puts address of the name
  2302                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2303                              <1> 
  2304                              <1> 	; / name - remove link name
  2305                              <1> 	mov	[u.namep], ebx
  2306                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2307                              <1> 	call	namei
  2308                              <1> 		; jsr r0,namei / find the i-number associated 
  2309                              <1> 			     ; / with the path name
  2310                              <1> 	;jc	error
  2311                              <1> 		; br error9 / not found
  2312                              <1> 	jnc	short sysunlink1
  2313                              <1> 	; 'file not found !' error
  2314                              <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2315                              <1> 	jmp	error
  2316                              <1> sysunlink1:
  2317                              <1> 	push	eax ; 24/12/2021
  2318                              <1> 	;push	ax
  2319                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2320                              <1> 	call	isdir
  2321                              <1> 		; jsr r0,isdir / is it a directory
  2322                              <1> 	;xor 	ax, ax
  2323                              <1> 	; 24/12/2021
  2324                              <1> 	xor	eax, eax
  2325                              <1> 	mov	[u.dirbuf], ax ; 0
  2326                              <1> 		; clr u.dirbuf / no, clear the location that will
  2327                              <1> 			   ; / get written into the i-number portion
  2328                              <1> 			 ; / of the entry
  2329                              <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2330                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2331                              <1> 	call	wdir
  2332                              <1> 		; jsr r0,wdir / free the directory entry
  2333                              <1> 	pop	eax ; 24/12/2021
  2334                              <1> 	;pop	ax
  2335                              <1> 		; mov (sp)+,r1 / get i-number back
  2336                              <1> 	call	iget
  2337                              <1> 		; jsr r0,iget / get i-node
  2338                              <1> 	call	setimod
  2339                              <1> 		; jsr r0,setimod / set modified flag
  2340                              <1> 	dec	byte [i.nlks]
  2341                              <1> 		; decb i.nlks / decrement the number of links
  2342                              <1> 	; 24/12/2021
  2343                              <1> 	jnz	short sysunlink_2
  2344                              <1> 	;jnz	sysret
  2345                              <1> 		; bgt sysret9 / if this was not the last link
  2346                              <1> 			    ; / to file return
  2347                              <1> 	; AX = r1 = i-number
  2348                              <1> 	call	anyi
  2349                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2350                              <1> 			 ; / Then free contents of file and destroy it.
  2351                              <1> sysunlink_2:
  2352                              <1> 	jmp	sysret
  2353                              <1> 		; br sysret9
  2354                              <1> 
  2355                              <1> mkdir:
  2356                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2357                              <1> 	; 04/12/2015 (14 byte directory names)
  2358                              <1> 	; 12/10/2015
  2359                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2360                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2361                              <1> 	;
  2362                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2363                              <1> 	; by u.namep into the current directory.
  2364                              <1> 	;
  2365                              <1> 	; INPUTS ->
  2366                              <1> 	;    u.namep - points to a file name 
  2367                              <1> 	;	           that is about to be a directory entry.
  2368                              <1> 	;    ii - current directory's i-number.	
  2369                              <1> 	; OUTPUTS ->
  2370                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2371                              <1> 	;    u.off - points to entry to be filled 
  2372                              <1> 	;	     in the current directory		
  2373                              <1> 	;    u.base - points to start of u.dirbuf.
  2374                              <1> 	;    r1 - contains i-number of current directory 
  2375                              <1> 	;	
  2376                              <1> 	; ((AX = R1)) output
  2377                              <1> 	;
  2378                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2379                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2380                              <1> 	;
  2381                              <1> 
  2382                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2383                              <1> 	xor 	eax, eax
  2384                              <1> 	mov     edi, u.dirbuf+2
  2385                              <1> 	mov	esi, edi
  2386                              <1> 	stosd
  2387                              <1> 	stosd
  2388                              <1> 	; 04/12/2015 (14 byte directory names)
  2389                              <1> 	stosd
  2390                              <1> 	stosw
  2391                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2392                              <1> 	mov	edi, esi ; offset to u.dirbuf
  2393                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2394                              <1> 	;mov 	ebp, [u.namep]
  2395                              <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2396                              <1> 		; esi = physical address (page start + offset)
  2397                              <1> 		; ecx = byte count in the page (1 - 4096)
  2398                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2399                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2400                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2401                              <1> mkdir_1: ; 1: 
  2402                              <1> 	inc	ebp ; 12/10/2015
  2403                              <1> 	;
  2404                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2405                              <1> 	 ; 01/08/2013
  2406                              <1> 	lodsb
  2407                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2408                              <1> 	and 	al, al
  2409                              <1> 	jz 	short mkdir_3 	  
  2410                              <1> 		; beq 1f / if null, done
  2411                              <1> 	cmp	al, '/'
  2412                              <1> 		; cmp r1,$'/ / is it a "/"?
  2413                              <1> 	je	short mkdir_err
  2414                              <1> 	;je	error
  2415                              <1> 		; beq error9 / yes, error
  2416                              <1> 	; 12/10/2015
  2417                              <1> 	;dec	cx
  2418                              <1> 	dec	ecx ; 24/12/2021
  2419                              <1> 	jnz	short mkdir_2
  2420                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2421                              <1> 	call	trans_addr_nm ; convert virtual address to physical
  2422                              <1> 		; esi = physical address (page start + offset)
  2423                              <1> 		; ecx = byte count in the page
  2424                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2425                              <1> mkdir_2:
  2426                              <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2427                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2428                              <1> 				     ; / a char?
  2429                              <1> 	je	short mkdir_1
  2430                              <1> 		; beq 1b / yes, go back
  2431                              <1> 	stosb
  2432                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2433                              <1> 	jmp 	short mkdir_1
  2434                              <1> 		; br 1b / get next char
  2435                              <1> mkdir_err:
  2436                              <1> 	; 17/06/2015
  2437                              <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2438                              <1> 	jmp	error
  2439                              <1> 
  2440                              <1> mkdir_3: ; 1:
  2441                              <1> 	mov	eax, [u.dirp]
  2442                              <1> 	mov	[u.off], eax
  2443                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2444                              <1> 				 ; / slot to u.off
  2445                              <1> 	; 08/01/2022
  2446                              <1> wdir:	; 24/12/2021 (Retro UNIX 386 v1.2)
  2447                              <1> 	; 29/04/2013
  2448                              <1>         mov     dword [u.base], u.dirbuf
  2449                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2450                              <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2451                              <1> 		; mov $10.,u.count / u.count = 10
  2452                              <1> 	; 08/01/2022
  2453                              <1> 	mov	eax, [ii]
  2454                              <1> 	;mov	ax, [ii] 
  2455                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2456                              <1> 	;mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2457                              <1> 	; 08/01/2022 (Retro UNIX 386 v2 file system inode)
  2458                              <1> 	mov	dx, 80h	; mov dx, IWRITE
  2459                              <1> 	call 	access
  2460                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2461                              <1> 				 ; / for writing
  2462                              <1> 	; AX = i-number of current directory
  2463                              <1> 	; 01/08/2013
  2464                              <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2465                              <1> 	;call	writei
  2466                              <1> 	;	; jsr r0,writei / write into directory
  2467                              <1> 	;retn	
  2468                              <1> 	;	; rts r0
  2469                              <1> 	; 24/12/2021
  2470                              <1> 	jmp	writei
  2471                              <1> 
  2472                              <1> %endif
  2473                              <1> 
  2474                              <1> 	; 01/01/2022
  2475                              <1> 	; 24/12/2021
  2476                              <1> 	; 11/12/2021
  2477                              <1> 	; 04/12/2021
  2478                              <1> 	; 30/11/2021
  2479                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2480                              <1> sysexec:
  2481                              <1> 	; 02/05/2021
  2482                              <1> 	; 27/03/2021
  2483                              <1> 	; 26/03/2021
  2484                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  2485                              <1> 	; 23/10/2015
  2486                              <1> 	; 10/10/2015, 18/10/2015, 19/10/2015
  2487                              <1> 	; 29/07/2015, 05/08/2015, 05/08/2015
  2488                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2489                              <1> 	; 01/07/2015, 02/07/2015, 20/07,2015
  2490                              <1> 	; 24/06/2015, 25/06/2021
  2491                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2492                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2493                              <1> 	;
  2494                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2495                              <1> 	; pointed to by 'name' in the sysexec call. 
  2496                              <1> 	; 'sysexec' performs the following operations:
  2497                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2498                              <1> 	;    2. obtains i-node of file to be executed via 'iget'.
  2499                              <1> 	;    3. sets trap vectors to system routines.
  2500                              <1> 	;    4. loads arguments to be passed to executing file into
  2501                              <1> 	;	highest locations of user's core
  2502                              <1> 	;    5. puts pointers to arguments in locations immediately
  2503                              <1> 	;	following arguments.
  2504                              <1> 	;    6.	saves number of arguments in next location.
  2505                              <1> 	;    7. initializes user's stack area so that all registers
  2506                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2507                              <1> 	;	to core when 'sysret' restores registers 
  2508                              <1> 	;	and does an rti.
  2509                              <1> 	;    8. inializes u.r0 and u.sp
  2510                              <1> 	;    9. zeros user's core down to u.r0
  2511                              <1> 	;   10.	reads executable file from storage device into core
  2512                              <1> 	;	starting at location 'core'.
  2513                              <1> 	;   11.	sets u.break to point to end of user's code with
  2514                              <1> 	;	data area appended.
  2515                              <1> 	;   12.	calls 'sysret' which returns control at location
  2516                              <1> 	;	'core' via 'rti' instruction.
  2517                              <1> 	;
  2518                              <1> 	; Calling sequence:
  2519                              <1> 	;	sysexec; namep; argp
  2520                              <1> 	; Arguments:
  2521                              <1> 	;	namep - points to pathname of file to be executed
  2522                              <1> 	;	argp  - address of table of argument pointers
  2523                              <1> 	;	argp1... argpn - table of argument pointers
  2524                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2525                              <1> 	; Inputs: (arguments)
  2526                              <1> 	; Outputs: -	
  2527                              <1> 	; ...............................................................
  2528                              <1> 	;
  2529                              <1> 	; Retro UNIX 386 v1 modification: 
  2530                              <1> 	;	User application runs in it's own virtual space 
  2531                              <1> 	;	which is izolated from kernel memory (and other
  2532                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2533                              <1> 	;	privilige mode. Virtual start address is always 0.
  2534                              <1> 	;	User's core memory starts at linear address 400000h
  2535                              <1> 	;	(the end of the 1st 4MB).
  2536                              <1> 	;
  2537                              <1> 	; Retro UNIX 8086 v1 modification: 
  2538                              <1> 	;	user/application segment and system/kernel segment
  2539                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2540                              <1> 	;	are different (user's registers are saved to 
  2541                              <1> 	;	and then restored from system's stack.)
  2542                              <1> 	;
  2543                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2544                              <1> 	;	      arguments which were in these registers;
  2545                              <1> 	;	      but, it returns by putting the 1st argument
  2546                              <1> 	;	      in 'u.namep' and the 2nd argument
  2547                              <1> 	;	      on top of stack. (1st argument is offset of the
  2548                              <1> 	;	      file/path name in the user's program segment.)
  2549                              <1> 	
  2550                              <1> 	;call	arg2
  2551                              <1> 	; * name - 'u.namep' points to address of file/path name
  2552                              <1> 	;          in the user's program segment ('u.segmnt')
  2553                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2554                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2555                              <1> 	;          which is on top of stack.
  2556                              <1> 	;
  2557                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2558                              <1> 
  2559                              <1> 	; 23/06/2015 (32 bit modifications)
  2560                              <1> 
  2561 000043F9 891D[C06E0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2562                              <1>         ; 18/10/2015
  2563 000043FF 890D[346F0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2564 00004405 E8D8040000          <1> 	call	namei
  2565                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2566                              <1> 			     ; / named in sysexec call in r1
  2567                              <1> 	;jc	error
  2568                              <1> 		; br error9
  2569 0000440A 730F                <1> 	jnc	short sysexec_0
  2570                              <1> 	;
  2571                              <1> 	; 'file not found !' error
  2572 0000440C C705[186F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2572 00004414 0000                <1>
  2573 00004416 E991F7FFFF          <1> 	jmp	error
  2574                              <1> 
  2575                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2576                              <1> 	; (executable file flag is checked in 'access')
  2577                              <1> 	; (following error message is in 'access' subroutine)
  2578                              <1> ;sysexec_not_exf:
  2579                              <1> 	;; 'not executable file !' error
  2580                              <1> 	;mov	dword [u.error], ERR_NOT_EXECUTABLE
  2581                              <1> 	;jmp	error 
  2582                              <1> sysexec_0:
  2583                              <1> 	; 26/03/2021 ('iget' will be called in 'access')
  2584                              <1> 	;call	iget
  2585                              <1> 	;	; jsr r0,iget / get i-node for file to be executed
  2586                              <1> 	;
  2587                              <1> 	;test	byte [i.flgs], 10h
  2588                              <1> 	;;test	word [i.flgs], 10h
  2589                              <1> 	;	; bit $20,i.flgs / is file executable
  2590                              <1> 	;jz	short sysexec_not_exf
  2591                              <1> 	;;jz	error
  2592                              <1> 	;	; beq error9
  2593                              <1> 	; 26/03/2021
  2594 0000441B 66BA4000            <1> 	mov	dx, 40h ; IEXEC - execute, owner
  2595 0000441F E8360F0000          <1> 	call	access
  2596                              <1> 	; ! we are here because there is execute permission !
  2597                              <1> 	; ('iopen' is not needed for regular files, from now on)
  2598                              <1> 
  2599                              <1> 	; 26/03/2021
  2600                              <1> 	;; 25/03/2021
  2601                              <1> 	;; (ref: Retro UNIX 386 v2, 'ux.s')
  2602                              <1> 	;mov	dx, 40h ; IEXEC - execute, owner
  2603                              <1> 	;;
  2604                              <1> 	;call	iopen
  2605                              <1> 	;	; jsr r0,iopen / gets i-node for file with i-number
  2606                              <1> 	;		     ; / given in r1 (opens file)
  2607                              <1> 	
  2608                              <1> 	; 26/03/2021
  2609                              <1> 	; AX = i-number of the file
  2610                              <1> 	;test	byte [i.flgs], 20h
  2611                              <1> 	;;test	word [i.flgs], 20h
  2612                              <1> 	;	; bit $40,i.flgs / test user id on execution bit
  2613                              <1> 	;jz	short sysexec_1
  2614                              <1> 	;	; beq 1f
  2615                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013
  2616                              <1> 	;	; tstb u.uid / test user id
  2617                              <1> 	;jna	short sysexec_1
  2618                              <1> 	;	; beq 1f / super user
  2619                              <1> 
  2620                              <1> 	;mov	cl, [i.uid]
  2621                              <1> 	;mov	[u.uid], cl ; 02/08/2013
  2622                              <1> 	;	; movb i.uid,u.uid / put user id of owner of file
  2623                              <1> 				 ; / as process user id
  2624                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2625                              <1> 	;mov	al, [i.flgs+1]
  2626 00004424 66833D[F66E0000]00  <1> 	cmp	word [u.uid], 0	; super user (root) ?
  2627                              <1> 	;jna	short sysexec_19 ; yes, super user
  2628                              <1> 	;; 02/05/2021
  2629 0000442C 7625                <1> 	jna	short sysexec_1	; don't set UID or GID
  2630                              <1> 
  2631                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2
  2632 0000442E A0[416B0000]        <1> 	mov	al, [i.flgs+1]
  2633                              <1> 
  2634                              <1> 	; test set user id on execution bit 
  2635 00004433 A808                <1> 	test	al, 08h ; ISUID flag (800h)
  2636                              <1> 	;jz	short sysexec_19
  2637                              <1> 	; 02/05/2021
  2638 00004435 741C                <1> 	jz	short sysexec_1 ; do not set group ID
  2639                              <1> 				; (if user ID will not be set)
  2640                              <1> 				; (02/05/2021)	
  2641                              <1> 	; set user id on exec (800h)
  2642                              <1> 	; 26/03/2021
  2643                              <1> sysexec_setuid:
  2644                              <1> 	;; 27/03/2021
  2645                              <1> 	;cmp	word [u.uid], 0
  2646                              <1> 	;;jna	short sysexec_19 ; super user
  2647                              <1> 	;; 02/05/2021
  2648                              <1> 	;jna	short sysexec_1 ; do not set group ID
  2649                              <1> 	;			; (if user ID will not be set)
  2650                              <1> 	;			; (02/05/2021)
  2651 00004437 668B0D[446B0000]    <1> 	mov	cx, [i.uid]
  2652 0000443E 66890D[F66E0000]    <1> 	mov	[u.uid], cx
  2653                              <1> sysexec_19:
  2654                              <1> 	; test set group id on execution bit 
  2655 00004445 A804                <1> 	test	al, 04h ; ISGID flag (400h)
  2656 00004447 740A                <1> 	jz	short sysexec_1
  2657                              <1> sysexec_setgid:
  2658                              <1> 	; set group id on exec (400h)
  2659 00004449 A0[466B0000]        <1> 	mov	al, [i.gid]
  2660 0000444E A2[FA6E0000]        <1> 	mov	[u.gid], al
  2661                              <1> 	;
  2662                              <1> sysexec_1:
  2663                              <1> 	; 24/12/2021
  2664                              <1> 	; 11/12/2021
  2665                              <1> 	; 04/12/2021
  2666                              <1> 	; 18/10/2015
  2667                              <1> 	; 10/10/2015
  2668                              <1> 	; 24/07/2015
  2669                              <1> 	; 21/07/2015
  2670                              <1> 	; 25/06/2015
  2671                              <1> 	; 24/06/2015
  2672                              <1>         ; Moving arguments to the end of [u.upage]
  2673                              <1> 	; (by regarding page borders in user's memory space)
  2674                              <1> 	;
  2675                              <1> 	; 10/10/2015
  2676                              <1> 	; 21/07/2015
  2677 00004453 89E5                <1> 	mov	ebp, esp ; (**)
  2678                              <1> 	; 18/10/2015
  2679 00004455 89EF                <1> 	mov 	edi, ebp
  2680 00004457 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2681                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2682 0000445C 29CF                <1> 	sub	edi, ecx
  2683 0000445E 89FC                <1> 	mov	esp, edi
  2684 00004460 31C0                <1> 	xor	eax, eax
  2685 00004462 A3[D06E0000]        <1> 	mov 	[u.nread], eax ; 0
  2686 00004467 49                  <1> 	dec	ecx ; 256 - 1
  2687 00004468 890D[CC6E0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2688                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2689                              <1> 	; 24/12/2021
  2690                              <1> sysexec_2:
  2691 0000446E 8B35[346F0000]      <1> 	mov	esi, [argv] ; 18/10/2015
  2692 00004474 E85A020000          <1> 	call	get_argp
  2693 00004479 B904000000          <1> 	mov	ecx, 4 ; mov ecx, 4
  2694                              <1> sysexec_3:
  2695 0000447E 21C0                <1> 	and	eax, eax
  2696 00004480 7454                <1> 	jz	short sysexec_6
  2697                              <1> 	; 18/10/2015
  2698 00004482 010D[346F0000]      <1> 	add	[argv], ecx ; 4
  2699                              <1> 	;inc	word [argc]
  2700                              <1> 	; 11/12/2021
  2701 00004488 FF05[306F0000]      <1> 	inc	dword [argc]
  2702                              <1> 	;
  2703 0000448E A3[C86E0000]        <1> 	mov	[u.base], eax
  2704                              <1>  	; 23/10/2015
  2705 00004493 66C705[106F0000]00- <1> 	mov	word [u.pcount], 0
  2705 0000449B 00                  <1>
  2706                              <1> sysexec_4:
  2707 0000449C E8EA140000          <1> 	call	cpass ; get a character from user's core memory
  2708 000044A1 750B                <1>         jnz	short sysexec_5
  2709                              <1> 		; (max. 255 chars + null)
  2710                              <1> 	; 18/10/2015
  2711 000044A3 28C0                <1> 	sub 	al, al
  2712 000044A5 AA                  <1> 	stosb
  2713 000044A6 FF05[D06E0000]      <1> 	inc	dword [u.nread]
  2714 000044AC EB28                <1> 	jmp	short sysexec_6
  2715                              <1> sysexec_5:
  2716 000044AE AA                  <1> 	stosb
  2717 000044AF 20C0                <1> 	and 	al, al
  2718 000044B1 75E9                <1> 	jnz	short sysexec_4
  2719 000044B3 B904000000          <1> 	mov	ecx, 4
  2720 000044B8 390D[2C6F0000]      <1> 	cmp	[ncount], ecx ; 4
  2721 000044BE 72AE                <1> 	jb	short sysexec_2
  2722 000044C0 8B35[286F0000]      <1> 	mov	esi, [nbase]
  2723 000044C6 010D[286F0000]      <1> 	add	[nbase], ecx ; 4	
  2724                              <1> 	;sub	[ncount], cx 
  2725                              <1> 	; 11/12/2021
  2726 000044CC 290D[2C6F0000]      <1> 	sub	[ncount], ecx
  2727 000044D2 8B06                <1> 	mov	eax, [esi]
  2728 000044D4 EBA8                <1> 	jmp	short sysexec_3
  2729                              <1> sysexec_6:
  2730                              <1> 	; 24/12/2021
  2731                              <1> 	; 18/10/2015
  2732                              <1> 	; argument list transfer from user's core memory to
  2733                              <1> 	; kernel stack frame is OK here.
  2734                              <1> 	; [u.nread] = ; argument list length
  2735                              <1> 	;mov	[argv], esp ; start address of argument list
  2736                              <1> 	;
  2737                              <1> 	; 18/10/2015
  2738                              <1> 	; 24/07/2015
  2739                              <1>         ; 21/07/2015
  2740                              <1> 	; 02/07/2015
  2741                              <1> 	; 25/06/2015
  2742                              <1> 	; 24/06/2015
  2743                              <1> 	; 23/06/2015
  2744                              <1> 	;
  2745 000044D6 8B1D[086F0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2746 000044DC 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2747 000044DE 740A                <1> 	jz	short sysexec_7
  2748 000044E0 A1[046F0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2749 000044E5 E8AEEAFFFF          <1> 	call	deallocate_page_dir
  2750                              <1> sysexec_7:
  2751 000044EA E8DEE9FFFF          <1> 	call	make_page_dir
  2752                              <1> 	;jc	short sysexec_14
  2753                              <1> 	;jc	panic  ; allocation error 
  2754                              <1> 	;	       ; after a deallocation would be nonsence !?
  2755                              <1> 	; 26/03/2021
  2756 000044EF 7243                <1> 	jc	short sysexec_panic
  2757                              <1> 	
  2758                              <1> 	; 24/07/2015
  2759                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2760                              <1> 	;     of the user's page directory
  2761                              <1> 	;     (It is needed for interrupts!)
  2762                              <1> 	; 18/10/2015
  2763 000044F1 8B15[A86D0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2764 000044F7 8B02                <1> 	mov	eax, [edx] ; physical address of
  2765                              <1> 			   ; kernel's first page table (1st 4 MB)
  2766                              <1> 			   ; (PDE 0 of kernel's page directory)
  2767 000044F9 8B15[046F0000]      <1> 	mov 	edx, [u.pgdir]
  2768 000044FF 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2769                              <1> 	;
  2770                              <1> 	; 20/07/2015
  2771 00004501 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2772                              <1> 	; 18/10/2015
  2773 00004506 BE[206F0000]        <1> 	mov	esi, pcore ; physical start address
  2774                              <1> sysexec_8:	
  2775 0000450B B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2776 00004510 E8D6E9FFFF          <1> 	call	make_page_table
  2777                              <1> 	;jc	panic
  2778                              <1> 	; 26/03/2021
  2779 00004515 721D                <1> 	jc	short sysexec_panic
  2780                              <1> 	;
  2781                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2782 00004517 E8DDE9FFFF          <1> 	call	make_page ; make new page, clear and set the pte
  2783                              <1> 	;jc	panic
  2784                              <1> 	; 26/03/2021
  2785 0000451C 7216                <1> 	jc	short sysexec_panic
  2786                              <1> 	;
  2787 0000451E 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2788                              <1> 	; ebx = virtual address (24/07/2015)
  2789                              <1> 	; 30/11/2021
  2790                              <1> 	;call 	add_to_swap_queue
  2791                              <1> 	; 18/10/2015
  2792 00004520 81FE[246F0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2793 00004526 7411                <1> 	je	short sysexec_9 ; yes
  2794 00004528 BE[246F0000]        <1> 	mov	esi, ecore  ; physical address of the last page
  2795                              <1> 	; 20/07/2015
  2796 0000452D BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2797                              <1> 	; ebx = virtual end address + segment base address - 4K
  2798 00004532 EBD7                <1>         jmp     short sysexec_8
  2799                              <1> sysexec_panic:
  2800                              <1> 	; 26/03/2021
  2801 00004534 E90BEFFFFF          <1> 	jmp	panic
  2802                              <1> 
  2803                              <1> sysexec_9:
  2804                              <1> 	; 11/12/2021
  2805                              <1> 	; 18/10/2015
  2806                              <1> 	; 26/08/2015
  2807                              <1> 	; 25/06/2015
  2808                              <1> 	; move arguments from kernel stack to [ecore]
  2809                              <1> 	; (argument list/line will be copied from kernel stack
  2810                              <1> 	; frame to the last (stack) page of user's core memory)
  2811                              <1> 	; 18/10/2015
  2812 00004539 8B3D[246F0000]      <1> 	mov	edi, [ecore]
  2813 0000453F 81C700100000        <1> 	add	edi, PAGE_SIZE
  2814                              <1> 	;movzx	eax, word [argc]
  2815                              <1> 	; 11/12/2021
  2816 00004545 A1[306F0000]        <1> 	mov	eax, [argc]
  2817 0000454A 09C0                <1> 	or	eax, eax
  2818 0000454C 7509                <1> 	jnz	short sysexec_10
  2819 0000454E 89FB                <1> 	mov 	ebx, edi
  2820 00004550 83EB04              <1> 	sub	ebx, 4 
  2821 00004553 8903                <1> 	mov	[ebx], eax ; 0
  2822 00004555 EB40                <1> 	jmp 	short sysexec_13
  2823                              <1> sysexec_10:
  2824 00004557 8B0D[D06E0000]      <1> 	mov	ecx, [u.nread]
  2825                              <1> 	;mov 	esi, [argv]
  2826 0000455D 89E6                <1> 	mov	esi, esp ; start address of argument list
  2827 0000455F 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2828 00004561 89C2                <1> 	mov	edx, eax
  2829 00004563 FEC2                <1> 	inc	dl ; argument count + 1 for argc value  
  2830 00004565 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2831 00004568 89FB                <1> 	mov	ebx, edi
  2832 0000456A 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2833 0000456D 29D3                <1> 	sub 	ebx, edx
  2834 0000456F 89FA                <1> 	mov	edx, edi
  2835 00004571 F3A4                <1> 	rep	movsb
  2836 00004573 89D6                <1> 	mov 	esi, edx
  2837 00004575 89DF                <1> 	mov 	edi, ebx
  2838 00004577 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2839 0000457C 2B15[246F0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2840 00004582 AB                  <1> 	stosd	; eax = argument count
  2841                              <1> sysexec_11:
  2842 00004583 89F0                <1> 	mov	eax, esi
  2843 00004585 01D0                <1> 	add	eax, edx
  2844 00004587 AB                  <1> 	stosd  ; eax = virtual address
  2845 00004588 FE0D[306F0000]      <1> 	dec	byte [argc]
  2846 0000458E 7407                <1> 	jz	short sysexec_13
  2847                              <1> sysexec_12:
  2848 00004590 AC                  <1> 	lodsb
  2849 00004591 20C0                <1> 	and	al, al
  2850 00004593 75FB                <1> 	jnz	short sysexec_12
  2851 00004595 EBEC                <1> 	jmp	short sysexec_11
  2852                              <1> 	;
  2853                              <1> 	; 1:
  2854                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2855                              <1> 			     ; / pointers to arguments to be passed
  2856                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2857                              <1> 			      ; / u.quit = 1 take quit
  2858                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2859                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2860                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2861                              <1> 			       ; / system routine
  2862                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector
  2863                              <1> 			       ; / set to take system routine
  2864                              <1> 		; mov $sstack,sp / stack space used during swapping
  2865                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2866                              <1> 		; mov $ecore,r5 / r5 has end of core
  2867                              <1> 		; mov $core,r4 / r4 has start of users core
  2868                              <1> 		; mov r4,u.base / u.base has start of users core
  2869                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2870                              <1> 	; 1:
  2871                              <1> 		; tst (r2)+ / argument char = "nul"
  2872                              <1> 		; bne 1b
  2873                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of
  2874                              <1> 			  ; / end of argument pointer list
  2875                              <1> 	; 1:
  2876                              <1> 	     ; / move arguments to bottom of users core
  2877                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2878                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2879                              <1> 			    ; / ptr list
  2880                              <1> 		; blo 1f / branch to 1f when all arguments
  2881                              <1> 		       ; / are moved
  2882                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2883                              <1> 	; 2:
  2884                              <1> 		; tstb (r3)+
  2885                              <1> 		; bne 2b / scan argument for \0 (nul)
  2886                              <1> 
  2887                              <1> 	; 2:
  2888                              <1> 		; movb -(r3),-(r5) / move argument char 
  2889                              <1> 				 ; / by char starting at "ecore"
  2890                              <1> 		; cmp r3,(r2) / moved all characters in 
  2891                              <1> 			    ; / this argument
  2892                              <1> 		; bhi 2b / branch 2b if not
  2893                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2894                              <1> 			     ; / r5 has pointer to nth arg
  2895                              <1> 		; br 1b / string
  2896                              <1> 	; 1:
  2897                              <1> 		; clrb -(r5)
  2898                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2899                              <1> 			; / last word of argument strings
  2900                              <1> 		; mov $core,r2
  2901                              <1> 	
  2902                              <1> 	; 1: / move argument pointers into core following 
  2903                              <1> 	      ; / argument strings
  2904                              <1> 		; cmp r2,r4
  2905                              <1> 		; bhis 1f / branch to 1f when all pointers
  2906                              <1> 			; / are moved
  2907                              <1> 		; mov (r2)+,-(r5)
  2908                              <1> 		; br 1b
  2909                              <1> 	; 1:
  2910                              <1> 		; sub $core,r4 / gives number of arguments *2
  2911                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2912                              <1> 		       ; / the number of args stored
  2913                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2914                              <1> 			     ; / of the argument pointers
  2915                              <1> sysexec_13:
  2916                              <1> 	; 30/11/2021
  2917                              <1> 	; 28/11/2021
  2918                              <1> 	; 19/10/2015
  2919                              <1> 	; 18/10/2015
  2920                              <1> 	; 29/07/2015
  2921                              <1> 	; 25/07/2015
  2922                              <1> 	; 24/07/2015
  2923                              <1> 	; 20/07/2015
  2924                              <1> 	; 25/06/2015
  2925                              <1> 	; 24/06/2015
  2926                              <1> 	; 23/06/2015
  2927                              <1> 	;
  2928                              <1> 	; moving arguments to [ecore] is OK here..
  2929                              <1> 	; 18/10/2015
  2930 00004597 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2931                              <1> 	; ebx = beginning address of argument list pointers
  2932                              <1> 	;	in user's stack
  2933                              <1> 	; 19/10/2015
  2934 00004599 2B1D[246F0000]      <1> 	sub 	ebx, [ecore]
  2935 0000459F 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2936                              <1> 			; end of core - 4096 (last page)
  2937                              <1> 			; (virtual address)
  2938 000045A5 891D[346F0000]      <1> 	mov	[argv], ebx
  2939 000045AB 891D[D46E0000]      <1> 	mov	[u.break], ebx ; available user memory
  2940                              <1> 	;
  2941 000045B1 29C0                <1> 	sub	eax, eax
  2942 000045B3 C705[CC6E0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2942 000045BB 0000                <1>
  2943                              <1> 		; mov $14,u.count
  2944 000045BD C705[B86E0000]-     <1> 	mov	dword [u.fofp], u.off
  2944 000045C3 [C46E0000]          <1>
  2945                              <1> 		; mov $u.off,u.fofp
  2946 000045C7 A3[C46E0000]        <1> 	mov	[u.off], eax ; 0
  2947                              <1> 		; clr u.off / set offset in file to be read to zero
  2948                              <1> 	; 25/07/2015
  2949 000045CC A3[C86E0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2950                              <1> 	; 25/06/2015 
  2951 000045D1 A1[806E0000]        <1> 	mov	eax, [ii] ; 28/11/2021 (32 bit inode number)
  2952                              <1> 	; AX = i-number of the executable file
  2953 000045D6 E8E40F0000          <1> 	call	readi
  2954                              <1> 		; jsr r0,readi / read in first six words of 
  2955                              <1> 			; / user's file, starting at $core
  2956                              <1> 		; mov sp,r5 / put users stack address in r5
  2957                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2958                              <1> 				; / from r5 (leaves number of words
  2959                              <1> 				; / less 26 available for
  2960                              <1> 			     	; / program in user core
  2961                              <1> 		; mov r5,u.count /
  2962                              <1> 	; 25/06/2015
  2963 000045DB 8B0D[D46E0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2964 000045E1 890D[CC6E0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2965                              <1> 	;
  2966 000045E7 8B0D[D06E0000]      <1> 	mov	ecx, [u.nread]
  2967 000045ED 890D[D46E0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2968 000045F3 80F920              <1> 	cmp	cl, 32
  2969 000045F6 7540                <1>         jne     short sysexec_15
  2970                              <1> 	;:
  2971                              <1> 	; 25/06/2015
  2972                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2973                              <1> 	; 18/10/2015
  2974 000045F8 8B35[206F0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2975                              <1> 		             ; (phys. start addr. of the exec. file)
  2976 000045FE AD                  <1> 	lodsd
  2977 000045FF 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  2978 00004603 7533                <1> 	jne	short sysexec_15
  2979                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2980                              <1> 			      ; / if file is standard a.out format
  2981                              <1> 		; bne 1f / branch, if not standard format
  2982 00004605 AD                  <1> 	lodsd
  2983 00004606 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2984 00004608 AD                  <1> 	lodsd
  2985 00004609 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2986                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2987                              <1> 		              ; / number of bytes in program text
  2988                              <1> 		; sub $14,r5 / subtract 12
  2989 0000460B 89CB                <1> 	mov	ebx, ecx
  2990                              <1> 	;
  2991                              <1> 	; 25/06/2015
  2992                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2993                              <1> 	;	and SINGLIX operating systems (as code template).
  2994                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2995                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2996                              <1> 	;	Overrun is not possible for current version.
  2997                              <1> 	;
  2998 0000460D AD                  <1> 	lodsd	
  2999 0000460E 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  3000 00004610 3B1D[CC6E0000]      <1> 	cmp	ebx, [u.count]
  3001 00004616 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  3002                              <1> 	;
  3003                              <1> 	; 24/07/2015
  3004                              <1> 	; add bss section size to [u.break]
  3005 00004618 0105[D46E0000]      <1> 	add 	[u.break], eax
  3006                              <1> 	;
  3007 0000461E 83E920              <1> 	sub	ecx, 32 ; header size (already loaded)
  3008                              <1> 	;cmp	ecx, [u.count]
  3009                              <1> 	;jnb	short sysexec_16
  3010                              <1> 		; cmp r5,u.count /
  3011                              <1> 		; bgt 1f / branch if r5 greater than u.count
  3012 00004621 890D[CC6E0000]      <1> 	mov	[u.count], ecx ; required read count
  3013                              <1> 		; mov r5,u.count
  3014                              <1> 	;
  3015 00004627 EB29                <1> 	jmp	short sysexec_16
  3016                              <1> 	;
  3017                              <1> sysexec_14:
  3018                              <1> 	; 23/06/2015
  3019                              <1> 	; insufficient (out of) memory
  3020 00004629 C705[186F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  3020 00004631 0000                <1>
  3021 00004633 E974F5FFFF          <1> 	jmp	error
  3022                              <1> 	;
  3023                              <1> sysexec_15:
  3024                              <1> 	; 25/06/2015
  3025                              <1>         ;movzx   edx, word [i.size] ; file size
  3026                              <1> 	; 30/11/2021
  3027 00004638 8B15[486B0000]      <1> 	mov	edx, [i.size] ; file size
  3028 0000463E 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  3029 00004640 7626                <1> 	jna	short sysexec_17 ; no need to next read
  3030 00004642 01D1                <1> 	add	ecx, edx ; [i.size]
  3031 00004644 3B0D[CC6E0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  3032 0000464A 77DD                <1> 	ja	short sysexec_14
  3033 0000464C 8915[CC6E0000]      <1> 	mov	[u.count], edx
  3034                              <1> sysexec_16:
  3035                              <1> 	;mov	ax, [ii] ; i-number
  3036                              <1> 	; 28/11/2021
  3037 00004652 A1[806E0000]        <1> 	mov	eax, [ii] ; 32 bit inode number
  3038 00004657 E8630F0000          <1> 	call	readi
  3039                              <1> 		; add core+10,u.nread / add size of user data area
  3040                              <1> 		                    ; / to u.nread
  3041                              <1> 		; br 2f
  3042                              <1> 	; 1:
  3043                              <1> 		; jsr r0,readi / read in rest of file
  3044                              <1> 	; 2:
  3045 0000465C 8B0D[D06E0000]      <1> 	mov	ecx, [u.nread]
  3046 00004662 010D[D46E0000]      <1> 	add	[u.break], ecx
  3047                              <1> 		; mov u.nread,u.break / set users program break to end of
  3048                              <1> 				    ; / user code
  3049                              <1> 		; add $core+14,u.break / plus data area
  3050                              <1> 	; 20/07/2015
  3051                              <1> sysexec_17:
  3052                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  3053                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3054                              <1> 	;;mov	ax, [ii] ; i-number
  3055                              <1> 	;call	iclose
  3056                              <1> 	;	; jsr r0,iclose / does nothing
  3057 00004668 31C0                <1>         xor     eax, eax
  3058 0000466A FEC0                <1> 	inc	al
  3059 0000466C 66A3[F06E0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3060 00004672 66A3[F26E0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3061                              <1> 	; 30/11/2021
  3062 00004678 FEC8                <1> 	dec	al  ; eax = 0
  3063                              <1> 	; 02/07/2015
  3064                              <1>         ;cmp	dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ?
  3065 0000467A 3905[086F0000]      <1> 	cmp	[u.ppgdir], eax ; 0 ; is the caller sys_init (kernel) ?
  3066 00004680 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3067                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3068 00004682 8B15[A86D0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3069 00004688 8915[086F0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here
  3070                              <1> sysexec_18:
  3071                              <1> 	; 18/10/2015
  3072                              <1> 	; 05/08/2015
  3073                              <1> 	; 29/07/2015
  3074 0000468E 8B2D[346F0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must points to argument
  3075                              <1> 			    ; list pointers (argument count)
  3076 00004694 FA                  <1> 	cli
  3077 00004695 8B25[446D0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3078                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3079                              <1> 			    ; for this process	 
  3080                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3081                              <1> 	;;xor	eax, eax ; 0
  3082                              <1> 	;dec	al ; eax = 0
  3083                              <1> 	; eax = 0 ; 30/11/2021 
  3084 0000469B 66BA2300            <1> 	mov	dx, UDATA
  3085 0000469F 6652                <1> 	push	dx  ; user's stack segment
  3086 000046A1 55                  <1> 	push	ebp ; user's stack pointer
  3087                              <1> 		    ; (points to number of arguments)
  3088 000046A2 FB                  <1> 	sti
  3089 000046A3 9C                  <1> 	pushfd	; EFLAGS
  3090                              <1> 		; Set IF for enabling interrupts in user mode
  3091                              <1> 	;or	dword [esp], 200h 
  3092                              <1> 	;
  3093                              <1> 	;mov	bx, UCODE
  3094                              <1> 	;push	bx ; user's code segment
  3095 000046A4 6A1B                <1> 	push	UCODE
  3096                              <1> 	;push	0
  3097 000046A6 50                  <1> 	push	eax ; EIP (=0) - start address -
  3098                              <1> 		; clr -(r5) / popped into ps when rti in 
  3099                              <1> 			  ; / sysrele is executed
  3100                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3101                              <1> 		                ; / in sysrele is executed
  3102                              <1> 		;mov r5,0f / load second copyz argument
  3103                              <1> 		;tst -(r5) / decrement r5
  3104 000046A7 8925[9C6E0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3105                              <1> 	; 05/08/2015
  3106                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3107                              <1> 	; ('push dx' would cause to general protection fault, 
  3108                              <1> 	; after 'pop ds' etc.)
  3109                              <1> 	;
  3110                              <1> 	;; push dx ; ds (UDATA)
  3111                              <1> 	;; push dx ; es (UDATA)
  3112                              <1> 	;; push dx ; fs (UDATA)
  3113                              <1> 	;; push dx ; gs (UDATA)
  3114                              <1> 	;
  3115                              <1> 	; This is a trick to prevent general protection fault
  3116                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3117 000046AD 8EC2                <1> 	mov 	es, dx ; UDATA
  3118 000046AF 06                  <1> 	push 	es ; ds (UDATA)
  3119 000046B0 06                  <1> 	push 	es ; es (UDATA)
  3120 000046B1 06                  <1> 	push 	es ; fs (UDATA)
  3121 000046B2 06                  <1> 	push	es ; gs (UDATA)
  3122 000046B3 66BA1000            <1> 	mov	dx, KDATA
  3123 000046B7 8EC2                <1> 	mov	es, dx
  3124                              <1> 	;
  3125                              <1> 	;; pushad simulation
  3126 000046B9 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3127 000046BB 50                  <1> 	push	eax ; eax (0)
  3128 000046BC 50                  <1> 	push	eax ; ecx (0)
  3129 000046BD 50                  <1> 	push	eax ; edx (0)
  3130 000046BE 50                  <1> 	push	eax ; ebx (0)
  3131 000046BF 55                  <1> 	push	ebp ; esp before pushad
  3132 000046C0 50                  <1> 	push	eax ; ebp (0)
  3133 000046C1 50                  <1> 	push	eax ; esi (0)		
  3134 000046C2 50                  <1> 	push	eax ; edi (0)	
  3135                              <1> 	;
  3136 000046C3 A3[A46E0000]        <1> 	mov	[u.r0], eax ; eax = 0
  3137 000046C8 8925[A06E0000]      <1> 	mov	[u.usp], esp
  3138                              <1> 		; mov r5,u.r0 /
  3139                              <1> 		; sub $16.,r5 / skip 8 words
  3140                              <1> 		; mov r5,u.sp / assign user stack pointer value,
  3141                              <1> 		;             / effectively zeroes all regs
  3142                              <1> 			    ; / when sysrele is executed
  3143                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3144                              <1> 		; clr u.break
  3145                              <1> 		; mov r5,sp / point sp to user's stack
  3146                              <1> 	;
  3147 000046CE E9FBF4FFFF          <1> 	jmp	sysret0
  3148                              <1> 	;jmp	sysret
  3149                              <1> 		; br sysret3 / return to core image at $core
  3150                              <1> 
  3151                              <1> get_argp:
  3152                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  3153                              <1> 	; 18/10/2015 (nbase, ncount)
  3154                              <1> 	; 21/07/2015
  3155                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3156                              <1> 	; Get (virtual) address of argument from user's core memory
  3157                              <1> 	;
  3158                              <1> 	; INPUT:
  3159                              <1> 	;	esi = virtual address of argument pointer
  3160                              <1> 	; OUTPUT:
  3161                              <1> 	;	eax = virtual address of argument
  3162                              <1> 	;
  3163                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3164                              <1> 	;
  3165 000046D3 833D[086F0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3166                              <1> 				    ; (the caller is kernel)
  3167 000046DA 767C                <1>         jna     short get_argpk 
  3168                              <1> 	;
  3169 000046DC 89F3                <1>      	mov	ebx, esi
  3170 000046DE E871EBFFFF          <1> 	call	get_physical_addr ; get physical address
  3171 000046E3 7254                <1>         jc	short get_argp_err ; 11/12/2021
  3172 000046E5 A3[286F0000]        <1> 	mov 	[nbase], eax ; physical address	
  3173                              <1> 	;mov	[ncount], cx ; remain byte count in page (1-4096)
  3174                              <1> 	; 11/12/2021
  3175 000046EA 890D[2C6F0000]      <1> 	mov	[ncount], ecx
  3176 000046F0 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3177                              <1> 	;cmp	cx, ax ; 4
  3178                              <1> 	; 11/12/2021
  3179 000046F5 39C1                <1> 	cmp	ecx, eax ; 4
  3180 000046F7 734A                <1> 	jnb	short get_argp2
  3181 000046F9 89F3                <1> 	mov	ebx, esi
  3182 000046FB 01CB                <1> 	add	ebx, ecx
  3183 000046FD E852EBFFFF          <1> 	call	get_physical_addr ; get physical address
  3184 00004702 7235                <1> 	jc	short get_argp_err
  3185                              <1> 	;push	esi
  3186 00004704 89C6                <1> 	mov	esi, eax
  3187                              <1> 	;xchg	cx, [ncount]
  3188                              <1> 	; 11/12/2021
  3189 00004706 870D[2C6F0000]      <1> 	xchg	ecx, [ncount]
  3190 0000470C 8735[286F0000]      <1> 	xchg	esi, [nbase]
  3191 00004712 B504                <1> 	mov	ch, 4
  3192 00004714 28CD                <1> 	sub	ch, cl
  3193                              <1> get_argp0:
  3194 00004716 AC                  <1> 	lodsb
  3195                              <1> 	;push	ax
  3196                              <1> 	; 11/12/2021
  3197 00004717 50                  <1> 	push	eax
  3198 00004718 FEC9                <1> 	dec	cl
  3199 0000471A 75FA                <1>         jnz     short get_argp0
  3200 0000471C 8B35[286F0000]      <1> 	mov	esi, [nbase]
  3201                              <1> 	; 21/07/2015
  3202 00004722 0FB6C5              <1> 	movzx	eax, ch
  3203 00004725 0105[286F0000]      <1> 	add	[nbase], eax
  3204                              <1> 	;sub	[ncount], ax
  3205                              <1> 	; 11/12/2021
  3206 0000472B 2905[2C6F0000]      <1> 	sub	[ncount], eax
  3207                              <1> get_argp1:
  3208 00004731 AC                  <1> 	lodsb
  3209 00004732 FECD                <1> 	dec	ch
  3210 00004734 743B                <1>         jz      short get_argp3
  3211                              <1>         ;push	ax
  3212                              <1> 	; 11/12/2021
  3213 00004736 50                  <1> 	push	eax
  3214 00004737 EBF8                <1> 	jmp     short get_argp1
  3215                              <1> get_argp_err:
  3216 00004739 A3[186F0000]        <1> 	mov	[u.error], eax
  3217 0000473E E969F4FFFF          <1> 	jmp	error
  3218                              <1> get_argp2:
  3219                              <1> 	; 21/07/2015
  3220                              <1> 	;mov	eax, 4
  3221 00004743 8B15[286F0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3222 00004749 0105[286F0000]      <1> 	add	[nbase], eax
  3223                              <1> 	;sub	[ncount], ax
  3224                              <1> 	; 11/12/2021
  3225 0000474F 2905[2C6F0000]      <1> 	sub	[ncount], eax
  3226                              <1> 	;
  3227 00004755 8B02                <1> 	mov	eax, [edx]
  3228 00004757 C3                  <1> 	retn
  3229                              <1> get_argpk:
  3230                              <1> 	; Argument is in kernel's memory space
  3231 00004758 66C705[2C6F0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3231 00004760 10                  <1>
  3232 00004761 8935[286F0000]      <1> 	mov	[nbase], esi
  3233 00004767 8305[286F0000]04    <1> 	add	dword [nbase], 4
  3234 0000476E 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physical addr.
  3235 00004770 C3                  <1> 	retn
  3236                              <1> get_argp3:
  3237 00004771 B103                <1> 	mov	cl, 3
  3238                              <1> get_argp4:
  3239 00004773 C1E008              <1> 	shl	eax, 8
  3240                              <1> 	;pop	dx
  3241                              <1> 	; 11/12/2021
  3242 00004776 5A                  <1> 	pop	edx
  3243 00004777 88D0                <1> 	mov 	al, dl
  3244 00004779 E2F8                <1>         loop    get_argp4
  3245                              <1> 	;pop	esi
  3246 0000477B C3                  <1> 	retn	
  3247                              <1> 
  3248                              <1> sysfstat: 
  3249                              <1> 	; 08/01/2022
  3250                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3251                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3252                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3253                              <1> 	;
  3254                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3255                              <1> 	; on open files instead of files given by name. It puts the
  3256                              <1> 	; buffer address on the stack, gets the i-number and
  3257                              <1> 	; checks to see if the file is open for reading or writing.
  3258                              <1> 	; If the file is open for writing (i-number is negative)
  3259                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3260                              <1> 	; is made.	
  3261                              <1> 	;
  3262                              <1> 	; Calling sequence:
  3263                              <1> 	;	sysfstat; buf
  3264                              <1> 	; Arguments:
  3265                              <1> 	;	buf - buffer address
  3266                              <1> 	;
  3267                              <1> 	; Inputs: *u.r0 - file descriptor
  3268                              <1> 	; Outputs: buffer is loaded with file information
  3269                              <1> 	; ...............................................................
  3270                              <1> 	;				
  3271                              <1> 	; Retro UNIX 8086 v1 modification:
  3272                              <1> 	;       'sysfstat' system call has two arguments; so,
  3273                              <1> 	;	* 1st argument, file descriptor is in BX register
  3274                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3275                              <1> 
  3276                              <1> 	; / set status of open file
  3277                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3278 0000477C 51                  <1> 	push	ecx ; *
  3279                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3280                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3281                              <1> 		; jsr r0,getf / get the files i-number
  3282                              <1> 	; BX = file descriptor (file number)
  3283 0000477D E8F3000000          <1> 	call	getf1
  3284 00004782 6621C0              <1> 	and	ax, ax ; i-number of the file
  3285                              <1> 		; tst	r1 / is it 0?
  3286                              <1> 	;jz	error
  3287                              <1> 		; beq error3 / yes, error
  3288                              <1> 	;jnz	short sysfstat1
  3289                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2 (runix v2 file system)
  3290 00004785 752D                <1> 	jnz	short sysstat1
  3291 00004787 C705[186F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3291 0000478F 0000                <1>
  3292 00004791 E916F4FFFF          <1> 	jmp	error
  3293                              <1> 	; 26/12/2021
  3294                              <1> ;sysfstat1:
  3295                              <1> 	;cmp	ah, 80h
  3296                              <1>         ;jb      short sysstat1
  3297                              <1> 	;	; bgt 1f / if i-number is negative (open for writing)
  3298                              <1> 	;neg	ax
  3299                              <1> 	;	; neg r1 / make it positive, then branch
  3300                              <1> 	; 08/01/2022
  3301                              <1> 	;jmp	short sysstat1
  3302                              <1> 		; br 1f / to 1f
  3303                              <1> sysstat:
  3304                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3305                              <1> 	; 18/10/2015
  3306                              <1> 	; 07/10/2015
  3307                              <1> 	; 02/09/2015
  3308                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3309                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3310                              <1> 	;
  3311                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3312                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3313                              <1> 	; long and information about the file placed in it.	
  3314                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3315                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3316                              <1> 	; is then loaded and the results are given in the UNIX
  3317                              <1> 	; Programmers Manual sysstat (II).	
  3318                              <1> 	;
  3319                              <1> 	; Calling sequence:
  3320                              <1> 	;	sysstat; name; buf
  3321                              <1> 	; Arguments:
  3322                              <1> 	;	name - points to the name of the file
  3323                              <1> 	;	buf - address of a 34 bytes buffer
  3324                              <1> 	; Inputs: -
  3325                              <1> 	; Outputs: buffer is loaded with file information
  3326                              <1> 	; ...............................................................
  3327                              <1> 	;				
  3328                              <1> 	; Retro UNIX 8086 v1 modification: 
  3329                              <1> 	;       'sysstat' system call has two arguments; so,
  3330                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3331                              <1> 	;	to get sysstat system call arguments from the user;
  3332                              <1> 	;	* 1st argument, name is pointed to by BX register
  3333                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3334                              <1> 	;
  3335                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3336                              <1> 	;	      arguments which were in these registers;
  3337                              <1> 	;	      but, it returns by putting the 1st argument
  3338                              <1> 	;	      in 'u.namep' and the 2nd argument
  3339                              <1> 	;	      on top of stack. (1st argument is offset of the
  3340                              <1> 	;	      file/path name in the user's program segment.)		 	
  3341                              <1> 	
  3342                              <1> 	; / ; name of file; buffer - get files status
  3343                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3344 00004796 891D[C06E0000]      <1> 	mov	[u.namep], ebx
  3345 0000479C 51                  <1> 	push	ecx ; *
  3346 0000479D E840010000          <1> 	call	namei
  3347                              <1> 		; jsr r0,namei / get the i-number for the file
  3348                              <1> 	;jc	error
  3349                              <1> 		; br error3 / no such file, error
  3350 000047A2 7310                <1> 	jnc	short sysstat1
  3351                              <1> 	; pop 	ecx
  3352                              <1> sysstat_err0:
  3353                              <1> 	; 'file not found !' error
  3354 000047A4 C705[186F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3354 000047AC 0000                <1>
  3355 000047AE E9F9F3FFFF          <1> 	jmp	error
  3356                              <1> 
  3357 000047B3 00                  <1> statx: db 0
  3358                              <1> 
  3359                              <1> sysstat1: ; 1:
  3360 000047B4 E8B70A0000          <1> 	call	iget
  3361                              <1> 		; jsr r0,iget / get the i-node into core
  3362                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3363                              <1> 	; 02/09/2015
  3364 000047B9 8F05[C86E0000]      <1> 	pop	dword [u.base] ; *
  3365                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3366 000047BF E855000000          <1> 	call	sysstat_gpa ; get physical address
  3367 000047C4 730A                <1> 	jnc 	short sysstat2
  3368                              <1> sysstat_err1:
  3369 000047C6 A3[186F0000]        <1> 	mov	dword [u.error], eax ; error code
  3370 000047CB E9DCF3FFFF          <1> 	jmp	error
  3371                              <1> sysstat2:
  3372 000047D0 A0[806E0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3373 000047D5 AA                  <1> 	stosb
  3374 000047D6 FF05[C86E0000]      <1> 	inc 	dword [u.base]
  3375                              <1> 	;dec 	cx
  3376 000047DC 49                  <1> 	dec	ecx ; 26/12/2021
  3377 000047DD 7505                <1> 	jnz	short sysstat3
  3378 000047DF E835000000          <1> 	call	sysstat_gpa
  3379                              <1> 	;jc	short sysstat_err1
  3380                              <1> sysstat3:
  3381 000047E4 A0[816E0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3382 000047E9 AA                  <1> 	stosb
  3383                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3384 000047EA FF05[C86E0000]      <1> 	inc 	dword [u.base]
  3385                              <1> 	;;dec 	word [u.pcount]
  3386                              <1> 	;dec	cx
  3387 000047F0 49                  <1> 	dec	ecx ; 26/12/2021
  3388 000047F1 7505                <1> 	jnz	short sysstat4
  3389 000047F3 E821000000          <1> 	call	sysstat_gpa
  3390                              <1> 	;jc	short sysstat_err1	
  3391                              <1> sysstat4:
  3392 000047F8 BE[406B0000]        <1> 	mov	esi, inode
  3393                              <1> 		; mov $inode,r2 / r2 points to i-node
  3394                              <1> sysstat5: ; 1:
  3395 000047FD A4                  <1> 	movsb
  3396                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3397 000047FE FF05[C86E0000]      <1> 	inc 	dword [u.base]
  3398                              <1> 	;;dec 	word [u.pcount]
  3399                              <1> 	;dec	cx
  3400 00004804 49                  <1> 	dec	ecx ; 26/12/2021
  3401 00004805 7505                <1> 	jnz	short sysstat6
  3402 00004807 E80D000000          <1> 	call	sysstat_gpa
  3403                              <1> 	;jc	short sysstat_err1
  3404                              <1> sysstat6:
  3405                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2
  3406 0000480C 81FE[806B0000]      <1> 	cmp	esi, inode + 64 ; Retro UNIX v2 inode		
  3407                              <1> 	;cmp	esi, inode + 32
  3408                              <1> 		; cmp r2,$inode+32 / done?
  3409 00004812 75E9                <1> 	jne	short sysstat5
  3410                              <1> 		; bne 1b / no, go back
  3411 00004814 E9B3F3FFFF          <1> 	jmp	sysret
  3412                              <1> 		; br sysret3 / return through sysret
  3413                              <1> 	;
  3414                              <1> sysstat_gpa: ; get physical address of file status buffer
  3415                              <1> 	; 02/09/2015
  3416 00004819 8B1D[C86E0000]      <1> 	mov 	ebx, [u.base]
  3417                              <1> 	; 07/10/2015
  3418 0000481F E830EAFFFF          <1> 	call	get_physical_addr ; get physical address
  3419                              <1> 	;jc	short sysstat_gpa1
  3420 00004824 72A0                <1> 	jc	short sysstat_err1
  3421                              <1> 	; 18/10/2015
  3422 00004826 89C7                <1> 	mov	edi, eax ; physical address
  3423                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3424                              <1> ;sysstat_gpa1:
  3425 00004828 C3                  <1> 	retn
  3426                              <1> 
  3427                              <1> fclose:
  3428                              <1> 	; 08/01/2022
  3429                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3430                              <1> 	; 08/04/2021
  3431                              <1> 	; 04/04/2021
  3432                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3433                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3434                              <1> 	;            (32 bit offset pointer modification)
  3435                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3436                              <1> 	;
  3437                              <1> 	; Given the file descriptor (index to the u.fp list)
  3438                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3439                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3440                              <1> 	; u.fp list is cleared. If all the processes that opened
  3441                              <1> 	; that file close it, then fsp etry is freed and the file
  3442                              <1> 	; is closed. If not a return is taken. 
  3443                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3444                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3445                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3446                              <1> 	; a check is made to see if the file is special.	
  3447                              <1> 	;
  3448                              <1> 	; INPUTS ->
  3449                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3450                              <1> 	;    u.fp - list of entries in the fsp table
  3451                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3452                              <1> 	; OUTPUTS ->
  3453                              <1> 	;    r1 - contains the same file descriptor
  3454                              <1> 	;    r2 - contains i-number
  3455                              <1> 	;
  3456                              <1> 	; ((AX = R1))
  3457                              <1> 	; ((Modified registers: edx, ebx, ecx, esi, edi, ebp))
  3458                              <1> 	;
  3459                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3460                              <1> 	;              if i-number of the file is 0. (error)
  3461                              <1> 
  3462                              <1> 	; 08/04/2021
  3463                              <1> 	; INPUT:
  3464                              <1> 	;	eax = file descriptor
  3465                              <1> 	; OUTPUT:
  3466                              <1> 	;	cf = 0 -> eax = file descriptor
  3467                              <1> 	;	cf = 1 -> eax = error code
  3468                              <1> 	;		  (al = 0 -> file not open)
  3469                              <1> 
  3470                              <1> 	; 18/08/2020
  3471                              <1> 	;movzx	edx, ax ; **
  3472 00004829 89C3                <1> 	mov	ebx, eax
  3473                              <1> 
  3474                              <1> 	; 18/08/2020
  3475                              <1> _fclose:
  3476 0000482B 53                  <1> 	push	ebx ; ***  ; file descriptor (index to u.fp)
  3477                              <1> 
  3478                              <1> 	;push	ax ; ***
  3479                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3480                              <1> 			     ; / the index to u.fp list)
  3481                              <1> 	; ebx = file descriptor/number
  3482 0000482C E844000000          <1> 	call	getf
  3483                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3484                              <1> 			    ; / cdev has device =, u.fofp 
  3485                              <1> 			    ; / points to 3rd word of fsp entry
  3486                              <1> 	;cmp	eax, 1 ; 18/08/2020
  3487 00004831 6683F801            <1> 	cmp	ax, 1 ; r1
  3488                              <1> 		; tst r1 / is i-number 0?
  3489 00004835 723C                <1> 	jb	short fclose_2
  3490                              <1> 		; beq 1f / yes, i-node not active so return
  3491                              <1> 		; tst (r0)+ / no, jump over error return
  3492                              <1> 	
  3493                              <1> 	;mov	ebx, edx ; **
  3494                              <1>  	; 18/08/2020
  3495 00004837 8B1C24              <1> 	mov	ebx, [esp]
  3496                              <1> 	;mov	edx, eax 
  3497                              <1> 	;;mov 	dx, ax ; *
  3498                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3499                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3500                              <1> 			    ; / which is index to u.fp ; **
  3501 0000483A C683[AE6E0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3502                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3503 00004841 8B1D[B86E0000]      <1> 	mov	ebx, [u.fofp]
  3504                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3505                              <1> 
  3506                              <1> 	; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3507                              <1> 	; ebx = 5th word of fsp entry (64 bit file offset)
  3508                              <1> fclose_0:
  3509                              <1> 	; 08/01/2022
  3510 00004847 FE4BFE              <1> 	dec	byte [ebx-2] ; 18/08/2020 - Retro UNIX 386 v2
  3511                              <1> 	;dec	byte [ebx+4] ; 18/06/2015
  3512                              <1> 		; decb 2(r1) / decrement the number of processes 
  3513                              <1> 			   ; / that have opened the file
  3514 0000484A 7927                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3515                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3516                              <1> 	;
  3517                              <1> 	;push	dx ; *
  3518                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3519                              <1> 	;;xor	ax, ax ; 0
  3520                              <1> 	;xor	eax, eax ; 18/08/2020
  3521                              <1> 		; clear 1st word of fsp entry
  3522                              <1> 	;mov	[ebx-8], ax ; 0 ; 18/08/2020
  3523                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3524 0000484C 66C743F80000        <1> 	mov	word [ebx-8], 0 ; clear 1st word of fsp entry ; i-number
  3525                              <1> 			; Note: 32 bit i-node number field is ready but
  3526                              <1> 			;	it is not used in current runix version.	
  3527                              <1> 
  3528                              <1> 	;;mov	[ebx-4], ax ; 0
  3529                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3530                              <1> 	;mov	al, [ebx+5] ; 18/06/2015
  3531                              <1> 	;	; tstb	3(r1) / has this file been deleted
  3532                              <1> 	;and	al, al
  3533                              <1> 	;jz	short fclose_1
  3534                              <1> 	;	; beq 2f / no, branch
  3535                              <1> 
  3536                              <1> 	;push	edx ; * ; 18/08/2020
  3537                              <1> 	;mov	eax, edx ; * ; 18/08/2020
  3538                              <1> 
  3539                              <1> 	;; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3540                              <1> 	;;test	byte [ebx-3], 80h ; open mode & status flags
  3541                              <1> 	; 04/04/2021 - Retro UNIX 386 v2 (new fsp structure)
  3542                              <1> 	;test	byte [ebx-4], 80h ; open mode & status flags 
  3543                              <1> 	;jz	short fclose_1	; deleted file flag (bit 7)
  3544                              <1> 
  3545                              <1> 	; 04/04/2021
  3546 00004852 31D2                <1> 	xor	edx, edx
  3547                              <1> 	; 08/01/2022
  3548 00004854 8A53FD              <1> 	mov	dl, [ebx-3] ; open mode & status flags
  3549 00004857 F6C280              <1> 	test	dl, 80h	    ; deleted file flag (bit 7)
  3550 0000485A 7409                <1> 	jz	short fclose_1 ; (not deleted -while open-)
  3551 0000485C 52                  <1> 	push	edx
  3552                              <1> 
  3553                              <1> 	; deleted file !
  3554                              <1> 
  3555                              <1> 	;mov	ax, dx ; *
  3556                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3557                              <1> 	; AX = inode number
  3558 0000485D E859040000          <1> 	call	anyi
  3559                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3560                              <1> 			    ; / check if file appears in fsp again
  3561                              <1> 	; 04/04/2021
  3562 00004862 5A                  <1> 	pop	edx
  3563                              <1> 	; 08/04/2021
  3564 00004863 720C                <1> 	jc	short fclose_3 ; error code in eax	
  3565                              <1> 	; 18/08/2020
  3566                              <1> 	; jmp short fclose_2
  3567                              <1> 
  3568                              <1> 	; ax = inode number
  3569                              <1> fclose_1: ; 2:
  3570                              <1> 	; 04/04/2021
  3571 00004865 80E201              <1> 	and	dl, 1
  3572 00004868 FEC2                <1> 	inc	dl ; 0 -> 1 (open for read), 1 -> 2 (open for write)
  3573                              <1> 	
  3574                              <1> 	;pop	eax ; * ; 18/08/2020 
  3575                              <1> 	;;pop	ax ; *
  3576                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3577 0000486A E883140000          <1> 	call	iclose ; close if it is special file 
  3578                              <1> 		; jsr r0,iclose / check to see if it is a special file
  3579                              <1> 	; 08/04/2021
  3580 0000486F 7302                <1> 	jnc	short fclose_2
  3581                              <1> fclose_3:
  3582 00004871 5B                  <1> 	pop	ebx  ; ***  ; file descriptor
  3583                              <1> 	; eax = error code
  3584 00004872 C3                  <1> 	retn
  3585                              <1> fclose_2: ; 1:
  3586 00004873 58                  <1> 	pop	eax ; *** ; 18/08/2020
  3587                              <1> 	;pop	ax ; ***
  3588                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3589 00004874 C3                  <1> 	retn
  3590                              <1> 		; rts r0
  3591                              <1> 
  3592                              <1> 	; 08/01/2022
  3593                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3594                              <1> getf:	; / get the device number and the i-number of an open file
  3595                              <1> 	; 13/05/2015
  3596                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3597                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3598                              <1> 
  3599                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3600                              <1> 	;
  3601                              <1> 	; 16/05/2021
  3602                              <1> 	; 27/03/2020 - Retro UNIX 386 v2 
  3603                              <1> 	;	(new open files -fsp- structure)
  3604                              <1> 	; 13/05/2015
  3605                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3606                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3607                              <1> 	
  3608                              <1> 	; INPUT: 
  3609                              <1> 	;    ;eax = file descriptor/number
  3610                              <1> 	;     ebx = file descriptor/number ; 18/08/2020 	
  3611                              <1> 	; OUTPUT:
  3612                              <1> 	;     bl = open mode & status flag ; 27/03/2020
  3613                              <1> 	;        (bit 0 open mode flag, 0 = read, 1 = write)  
  3614                              <1> 	;    eax = inode number (in AX)
  3615                              <1> 	;          If eax = 0 -> file not open
  3616                              <1> 	;   byte [cdev] = logical drive number (of inode in eax)
  3617                              <1> 	;	
  3618                              <1> 	; Modified registers: eax, ebx
  3619                              <1> 
  3620                              <1> 	; 16/05/2021 ('getf' procedure, unix v7 x86 'fio.c')
  3621                              <1> 	; /*
  3622                              <1> 	;  * Convert a user supplied
  3623                              <1> 	;  * file descriptor into a pointer
  3624                              <1> 	;  * to a file structure.
  3625                              <1> 	;  * Only task is to check range
  3626                              <1> 	;  * of the descriptor.
  3627                              <1> 	;  */
  3628                              <1> 	; struct file *
  3629                              <1> 	; getf(f)
  3630                              <1> 	;
  3631                              <1> 	; 18/08/2020
  3632                              <1> 	; 	ebx = file descriptor/number
  3633                              <1> 
  3634                              <1> 	; 16/05/2021
  3635                              <1> 	;NOFILE	equ 10 ; 08/01/2022
  3636                              <1> 
  3637                              <1> 	; 18/08/2020
  3638                              <1> 	;mov	ebx, eax
  3639                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3640                              <1> 
  3641                              <1> 	; ebx = file descriptor/number
  3642                              <1> 
  3643                              <1> 	; 18/08/2020
  3644 00004875 29C0                <1> 	sub	eax, eax ; eax = 0
  3645                              <1>  
  3646 00004877 83FB0A              <1> 	cmp	ebx, 10 ; cmp ebx, NOFILE ; 16/05/2021
  3647                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3648 0000487A 7365                <1>         jnb	short getf2 ; 13/05/2015
  3649                              <1> 	;jnb	error
  3650                              <1> 		; bhis error3 / u.fp is table of users open files,
  3651                              <1> 			    ; / index in fsp table
  3652                              <1> 	; 08/01/2022
  3653 0000487C 8A83[AE6E0000]      <1> 	mov	al, [ebx+u.fp]
  3654                              <1> 	;mov	bl, [ebx+u.fp]
  3655                              <1> 		; movb u.fp(r1),r1 / r1 contains number of entry 
  3656                              <1> 		                 ; / in fsp table
  3657 00004882 08C0                <1> 	or	al, al ; 08/01/2022
  3658                              <1> 	;or	bl, bl
  3659                              <1> 	;jnz	short getf3
  3660 00004884 745B                <1> 	jz	short getf2 ; 18/08/2020
  3661                              <1> 	;;jz	short getf4
  3662                              <1> 		; beq 1f / if its zero return
  3663                              <1> ;getf2:
  3664                              <1> ;	; 'File not open !' error (ax=0)
  3665                              <1> ;	;sub	eax, eax ; 18/08/2020
  3666                              <1> ;	retn
  3667                              <1> ;getf3:	
  3668                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3669                              <1> 	;
  3670                              <1> 	; 'fsp' table (10 bytes/entry)
  3671                              <1> 	; bit 15				   bit 0
  3672                              <1> 	; ---|-------------------------------------------
  3673                              <1> 	; r/w|		i-number of open file
  3674                              <1> 	; ---|-------------------------------------------
  3675                              <1> 	;		   device number
  3676                              <1> 	; -----------------------------------------------
  3677                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3678                              <1> 	; -----------------------------------------------
  3679                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3680                              <1> 	; ----------------------|------------------------
  3681                              <1> 	;  flag that says file 	| number of processes
  3682                              <1> 	;   has been deleted	| that have file open 
  3683                              <1> 	; ----------------------|------------------------
  3684                              <1> 
  3685                              <1> 	; Retro UNIX 386 v2 modification ! (27/03/2020)
  3686                              <1> 
  3687                              <1> 	; bit 15 				    bit 0
  3688                              <1> 	; ----------------------------------------------- byte 0
  3689                              <1> 	;    	       i-number of open file           
  3690                              <1> 	; ----------------------------------------------- byte 2
  3691                              <1> 	;          high word of 32 bit i-number       
  3692                              <1> 	; ----------------------------------------------- byte 4
  3693                              <1> 	;    open mode & status  |   device number     
  3694                              <1> 	; ----------------------------------------------- byte 6
  3695                              <1> 	;       reserved byte    |    open count  
  3696                              <1> 	; ----------------------------------------------- byte 8
  3697                              <1> 	;   offset pointer, i.e., r/w pointer to file 
  3698                              <1> 	; ----------------------------------------------- byte 10
  3699                              <1> 	;     64 bit file offset pointer (bit 16-31)  
  3700                              <1> 	; ----------------------------------------------- byte 12
  3701                              <1> 	;     64 bit file offset pointer (bit 32-47)   
  3702                              <1> 	; ----------------------------------------------- byte 14
  3703                              <1> 	;     64 bit file offset pointer (bit 48-63)  
  3704                              <1> 	; ----------------------------------------------- byte 16
  3705                              <1> 	
  3706                              <1> 	; 11/05/2015 - Retro UNIX 386 v1
  3707                              <1> 	;mov	eax, 10
  3708                              <1> 
  3709                              <1> 	; 27/03/2020 - Retro UNIX 386 v2	
  3710                              <1> 	;mov	eax, opfls.size ; mov eax, 16
  3711                              <1> 	
  3712                              <1> 	;sub	eax, eax ; 18/08/2020 ; eax = 0
  3713                              <1> 
  3714                              <1> 	;mov	al, opfls.size  ; mov al, 16
  3715                              <1> 	;
  3716                              <1> 	;mul	bl
  3717                              <1> 	;;mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3718                              <1> 	;; 27/03/2020
  3719                              <1> 	;mov	ebx, fsp-(opfls.size-opfls.offset) ; fsp-8
  3720                              <1> 	
  3721                              <1> 	;add	ebx, eax
  3722                              <1> 		; asl r1
  3723                              <1> 		; asl r1 / multiply by 8 to get index into 
  3724                              <1> 		       ; / fsp table entry
  3725                              <1> 		; asl r1
  3726                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3727                              <1> 			      ; / in the fsp entry
  3728                              <1> 	; 08/01/2022
  3729 00004886 88C3                <1> 	mov	bl, al
  3730                              <1> 	; 18/08/2020
  3731 00004888 FECB                <1> 	dec	bl ; zero based fsp table entry number
  3732                              <1> 
  3733                              <1> ; temporary - 26/12/2021
  3734 0000488A 881D[E5400000]      <1> mov	[bytype], bl
  3735                              <1> 
  3736                              <1> 	;shl	bl, 4 ; * 16 ; opfls.size
  3737                              <1> 	; 08/01/2022
  3738 00004890 C1E304              <1> 	shl	ebx, 4 ; * 16 ; opfls.size
  3739 00004893 81C3[486B0000]      <1> 	add	ebx, fsp+8 ; opfls.offset	
  3740                              <1> 	; ebx = address of the file offset pointer 
  3741                              <1> 	;	(not file offset! not fsp entry address !)
  3742                              <1> 
  3743 00004899 891D[B86E0000]      <1> 	mov	[u.fofp], ebx
  3744                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3745                              <1> 			     ; / in fsp entry in u.fofp
  3746                              <1> 	; 18/08/2020
  3747 0000489F 8A43FD              <1> 	mov	al, [ebx-3]  ; open mode & status flags
  3748                              <1> 
  3749 000048A2 50                  <1> 	push	eax
  3750                              <1> 
  3751                              <1> 	;mov	ax, [ebx]
  3752                              <1> 	;;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3753                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3754                              <1> 			     ;;dev number is in 1 byte
  3755                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3756                              <1> 	
  3757                              <1> ; temporary - 26/12/2021
  3758 000048A3 53                  <1> push	ebx
  3759 000048A4 0205[6F3F0000]      <1> add	al, [srwtype]
  3760 000048AA 8B1D[E1400000]      <1> mov	ebx, [openaddr]
  3761 000048B0 8005[E1400000]02    <1> add	byte [openaddr], 2
  3762 000048B7 B44E                <1> mov	ah, 4Eh
  3763 000048B9 668903              <1> mov	word [ebx], ax
  3764 000048BC 8B1D[E1400000]      <1> mov	ebx, [openaddr]
  3765 000048C2 8005[E1400000]02    <1> add	byte [openaddr], 2
  3766 000048C9 A0[E5400000]        <1> mov	al, [bytype]
  3767 000048CE 0430                <1> add	al, '0'
  3768 000048D0 668903              <1> mov	word [ebx], ax
  3769 000048D3 5B                  <1> pop	ebx
  3770                              <1> 
  3771                              <1> 	; 18/08/2020
  3772 000048D4 8A43FC              <1> 	mov	al, [ebx-4]  ; logical drive number
  3773                              <1> 
  3774 000048D7 A2[856E0000]        <1> 	mov	[cdev], al
  3775                              <1> 
  3776                              <1> 	;dec	ebx
  3777                              <1> 	;dec	ebx
  3778                              <1> 	; 18/08/2020
  3779 000048DC 668B43F8            <1> 	mov	ax, [ebx-8]
  3780                              <1> 		; mov -(r1),r1 / and the i-number r1
  3781                              <1> 
  3782 000048E0 5B                  <1> 	pop	ebx ; ebx = bl = open mode and status flag
  3783                              <1> 		; (bit 0 is open mode flag, 0 = read, 1 = write)
  3784                              <1> 	; eax = inode number (in ax)	
  3785                              <1> 
  3786                              <1> getf2:	; 18/08/2020
  3787                              <1> getf4:	; 1: ; 08/01/2022
  3788 000048E1 C3                  <1> 	retn
  3789                              <1> 		; rts r0
  3790                              <1> 
  3791                              <1> 	; 08/01/2022
  3792                              <1> 	; 19/12/2021
  3793                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3794                              <1> namei:
  3795                              <1> 	; 18/10/2021
  3796                              <1> 	; 12/06/2021
  3797                              <1> 	; 01/05/2021
  3798                              <1> 	; 26/03/2021
  3799                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  3800                              <1> 	; 04/12/2015 (14 byte file names)
  3801                              <1> 	; 18/10/2015 (nbase, ncount)
  3802                              <1> 	; 12/10/2015
  3803                              <1> 	; 21/08/2015
  3804                              <1> 	; 18/07/2015
  3805                              <1> 	; 02/07/2015
  3806                              <1> 	; 17/06/2015
  3807                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3808                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3809                              <1> 	;
  3810                              <1> 	; 'namei' takes a file path name and returns i-number of
  3811                              <1> 	; the file in the current directory or the root directory
  3812                              <1> 	; (if the first character of the pathname is '/').	
  3813                              <1> 	;
  3814                              <1> 	; INPUTS ->
  3815                              <1> 	;    u.namep - points to a file path name
  3816                              <1> 	;    u.cdir - i-number of users directory
  3817                              <1> 	;    u.cdev - device number on which user directory resides	
  3818                              <1> 	; OUTPUTS ->
  3819                              <1> 	;    r1 - i-number of file
  3820                              <1> 	;    cdev
  3821                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3822                              <1> 	;               occurs in the search for file path name.
  3823                              <1> 	;	        If no match u.dirb points to the end of 
  3824                              <1> 	;               the directory and r1 = i-number of the current
  3825                              <1> 	;	        directory.	
  3826                              <1> 	; ((AX = R1))
  3827                              <1> 	;
  3828                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3829                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3830                              <1> 	;
  3831                              <1> 
  3832                              <1> 	;mov	ax, [u.cdir]
  3833                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3834                              <1> 			      ; / in r1
  3835                              <1> 	; 01/05/2021
  3836 000048E2 A1[A86E0000]        <1> 	mov	eax, [u.cdir]	
  3837 000048E7 8A15[AC6E0000]      <1> 	mov	dl, [u.cdrv]
  3838 000048ED 8815[856E0000]      <1> 	mov	[cdev], dl
  3839                              <1> 	;mov	dx, [u.cdrv]
  3840                              <1> 	;mov	[cdev], dx	; NOTE: Retro UNIX 8086 v1 
  3841                              <1> 				; device/drive number is in 1 byte, 
  3842                              <1> 				; not in 1 word!
  3843                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3844                              <1> 				; / into cdev
  3845                              <1> 	; 12/10/2015
  3846                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3847                              <1>       	; convert virtual (pathname) addr to physical address
  3848 000048F3 E808010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3849                              <1> 		; esi = physical address of [u.namep]
  3850                              <1> 		; ecx = byte count in the page
  3851 000048F8 803E2F              <1> 	cmp	byte [esi], '/'
  3852                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3853 000048FB 751C                <1> 	jne	short namei_1
  3854                              <1> 		; bne 1f
  3855 000048FD FF05[C06E0000]      <1> 	inc	dword [u.namep]
  3856                              <1> 		; inc u.namep / go to next char
  3857                              <1> 	;dec	cx ; remain byte count in the page
  3858 00004903 49                  <1> 	dec	ecx ; 18/10/2021
  3859 00004904 7506                <1> 	jnz	short namei_0
  3860                              <1> 	; 12/10/2015
  3861 00004906 E8F5000000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3862                              <1> 		; esi = physical address (page start + offset)
  3863                              <1> 		; ecx = byte count in the page
  3864 0000490B 4E                  <1> 	dec	esi
  3865                              <1> namei_0:
  3866 0000490C 46                  <1> 	inc 	esi  ; go to next char
  3867                              <1> 	;mov	ax, [rootdir] ; 09/07/2013
  3868                              <1> 	; 18/10/2021
  3869 0000490D A1[8C6E0000]        <1> 	mov	eax, [rootdir]
  3870                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3871 00004912 C605[856E0000]00    <1> 	mov	byte [cdev], 0
  3872                              <1> 		; clr cdev / clear device number
  3873                              <1> namei_1: ; 1:
  3874 00004919 F606FF              <1> 	test	byte [esi], 0FFh
  3875                              <1> 	;jz	short getf4
  3876                              <1> 	; 26/03/2021
  3877                              <1> 	;jz	short getf2 ; retn
  3878                              <1> 	;;jz	nig
  3879                              <1> 		; tstb *u.namep / is the character in file name a nul
  3880                              <1> 		; beq nig / yes, end of file name reached; 
  3881                              <1> 			; / branch to "nig"
  3882                              <1> 	; 19/12/2021
  3883                              <1> namei_9:
  3884                              <1> 	; 12/06/2021
  3885                              <1> 	;jnz	short namei_2
  3886                              <1> 	;retn
  3887                              <1> 	; 08/01/2022
  3888 0000491C 74C3                <1> 	jz	short getf4
  3889                              <1> namei_2: ; 1:
  3890                              <1> 	; 18/10/2015
  3891 0000491E 8935[286F0000]      <1> 	mov 	[nbase], esi
  3892                              <1> 	;mov 	[ncount], cx
  3893                              <1> 	; 18/10/2021
  3894 00004924 890D[2C6F0000]      <1> 	mov	[ncount], ecx
  3895                              <1> 	;
  3896                              <1> 	;;mov	dx, 2
  3897                              <1> 	;mov	dl, 2 ; user flag (read, non-owner)
  3898                              <1> 	; 25/03/2021
  3899                              <1> 	;mov	dx, 100h ; IREAD - read, owner 
  3900                              <1> 	; 18/10/2021
  3901 0000492A 29D2                <1> 	sub	edx, edx
  3902 0000492C FEC6                <1> 	inc	dh ; dx = 100h ; IREAD - read, owner 
  3903 0000492E E8270A0000          <1> 	call	access
  3904                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3905                              <1> 	; 'access' will not return here if user has not "r" permission !
  3906                              <1> 
  3907                              <1> 	;test 	word [i.flgs], 4000h
  3908                              <1> 	;	; bit $40000,i.flgs / directory i-node?
  3909                              <1>         ;jz	short namei_err
  3910                              <1> 		; beq error3 / no, got an error
  3911                              <1> 	; 26/03/2021 
  3912                              <1> ;	mov	al, [i.flgs+1]
  3913                              <1> ;	;test	al, 80h ; IFREG ; 80h
  3914                              <1> ;	;jz	short namei_err ; not a regular file ! (device!?)
  3915                              <1> ;	;and	al, 40h ; IFDIR ; 40h
  3916                              <1> ;	;jz	short namei_err ; not a sub directory !
  3917                              <1> ;	shl	al, 1 ; 80h (IFREG flag) -> cf = 1
  3918                              <1> ;	jnc	short namei_err ; not a regular file ! (device!?)
  3919                              <1> ;	shl	al, 1 ; 80h (IFDIR flag) -> cf = 1
  3920                              <1> ;	jnc	short namei_err ; not a sub directory !
  3921                              <1> 
  3922                              <1> 	; 27/03/2021
  3923 00004933 E8F9000000          <1> 	call	chk_dir ; check for directory, jump to 'error' if not
  3924                              <1> 	; CPU will be here if the inode is a (valid) directory inode
  3925                              <1> 
  3926                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3927                              <1> 	;xor	eax, eax
  3928                              <1> 	;mov	[u.off], eax ; 0
  3929                              <1> 	; 01/05/2021 - Retro UNIX 386 v2 inode structure
  3930 00004938 A1[486B0000]        <1> 	mov	eax, [i.size]
  3931                              <1> 	;mov	ax, [i.size]
  3932 0000493D A3[BC6E0000]        <1> 	mov	[u.dirp], eax
  3933                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3934                              <1> 		; clr u.off / u.off is file offset used by user
  3935                              <1> 	; 18/10/2021
  3936 00004942 31C0                <1> 	xor	eax, eax
  3937                              <1> 	;mov	[u.off], eax ; 0
  3938 00004944 BB[C46E0000]        <1> 	mov	ebx, u.off
  3939 00004949 8903                <1> 	mov	[ebx], eax ; mov dword [u.off], 0
  3940                              <1> 	;
  3941 0000494B 891D[B86E0000]      <1> 	mov	[u.fofp], ebx ; u.off ; 18/10/2021
  3942                              <1> 	;mov	dword [u.fofp], u.off
  3943                              <1> 			; mov $u.off,u.fofp / u.fofp is a pointer to 
  3944                              <1> 				  ; / the offset portion of fsp entry
  3945                              <1> namei_3: ; 2:
  3946 00004951 C705[C86E0000]-     <1> 	mov	dword [u.base], u.dirbuf
  3946 00004957 [DC6E0000]          <1>
  3947                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3948                              <1> 				    ; / copied from a directory
  3949 0000495B C705[CC6E0000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3949 00004963 0000                <1>
  3950                              <1>  		; mov $10.,u.count / u.count is byte count 
  3951                              <1> 				 ; / for reads and writes
  3952                              <1> 	;mov 	ax, [ii]
  3953                              <1> 	; 18/10/2021
  3954 00004965 A1[806E0000]        <1> 	mov	eax, [ii] ; (32 bit inode number)
  3955                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3956 0000496A FE05[166F0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3957 00004970 E84A0C0000          <1>     	call	readi
  3958                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3959                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3960                              <1> 
  3961 00004975 8B0D[D06E0000]      <1> 	mov 	ecx, [u.nread]
  3962 0000497B 09C9                <1> 	or 	ecx, ecx
  3963                              <1> 		; tst u.nread
  3964 0000497D 741A                <1> 	jz	short nib
  3965                              <1> 		; ble nib / gives error return
  3966                              <1> 	;
  3967                              <1> 	;mov 	bx, [u.dirbuf]
  3968                              <1> 	;and 	bx, bx       
  3969                              <1> 	; 18/10/2021
  3970 0000497F 66F705[DC6E0000]FF- <1> 	test	word [u.dirbuf], 0FFFFh
  3970 00004987 FF                  <1>
  3971                              <1> 		; tst u.dirbuf /
  3972 00004988 7513                <1> 	jnz	short namei_4
  3973                              <1> 		; bne 3f / branch when active directory entry 
  3974                              <1> 		       ; / (i-node word in entry non zero)
  3975 0000498A A1[C46E0000]        <1> 	mov	eax, [u.off]
  3976 0000498F 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3977 00004992 A3[BC6E0000]        <1> 	mov	[u.dirp], eax
  3978                              <1> 		; mov u.off,u.dirp
  3979                              <1> 		; sub $10.,u.dirp
  3980 00004997 EBB8                <1> 	jmp	short namei_3
  3981                              <1> 		; br 2b
  3982                              <1> 
  3983                              <1> 	; 18/07/2013
  3984                              <1> nib: 
  3985 00004999 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3986 0000499B F9                  <1> 	stc
  3987                              <1> nig:
  3988 0000499C C3                  <1> 	retn
  3989                              <1> 
  3990                              <1> 	; 27/03/2021
  3991                              <1> ;namei_err:
  3992                              <1> 	; 16/06/2015
  3993                              <1> ;	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3994                              <1> ;	jmp	error
  3995                              <1> 
  3996                              <1> namei_4: ; 3:
  3997                              <1> 	; 18/10/2015
  3998                              <1> 	; 12/10/2015
  3999                              <1> 	; 21/08/2015
  4000                              <1> 	; 18/07/2015
  4001 0000499D 8B2D[C06E0000]      <1> 	mov	ebp, [u.namep]
  4002                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  4003 000049A3 BF[DE6E0000]        <1> 	mov 	edi, u.dirbuf + 2
  4004                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  4005                              <1> 	; 18/10/2015
  4006 000049A8 8B35[286F0000]      <1> 	mov	esi, [nbase]
  4007                              <1> 	;mov	cx, [ncount]
  4008                              <1> 	;and	cx, cx
  4009                              <1> 	; 18/10/2021
  4010 000049AE 8B0D[2C6F0000]      <1> 	mov	ecx, [ncount]
  4011 000049B4 21C9                <1> 	and	ecx, ecx
  4012 000049B6 7505                <1> 	jnz	short namei_5	
  4013                              <1> 	;
  4014 000049B8 E849000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4015                              <1> 		; esi = physical address (page start + offset)
  4016                              <1> 		; ecx = byte count in the page
  4017                              <1> namei_5: ; 3:
  4018 000049BD 45                  <1> 	inc	ebp ; 18/07/2015
  4019 000049BE AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  4020                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  4021 000049BF 08C0                <1> 	or 	al, al
  4022 000049C1 741C                <1> 	jz 	short namei_7
  4023                              <1> 		; beq 3f / if char is nul, then the last char in string
  4024                              <1> 			; / has been moved
  4025 000049C3 3C2F                <1> 	cmp	al, '/'
  4026                              <1> 		; cmp r4,$'/ / is char a </>
  4027 000049C5 7418                <1> 	je 	short namei_7
  4028                              <1> 		; beq 3f	
  4029                              <1> 	; 12/10/2015
  4030                              <1> 	;dec	cx ; remain byte count in the page
  4031 000049C7 49                  <1> 	dec	ecx ; 18/10/2021
  4032 000049C8 7505                <1> 	jnz	short namei_6
  4033 000049CA E837000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  4034                              <1> 		; esi = physical address (page start + offset)
  4035                              <1> 		; ecx = byte count in the page
  4036                              <1> namei_6:
  4037 000049CF 81FF[EC6E0000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4038                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  4039                              <1> 				     ; / all 8 bytes of file name
  4040 000049D5 74E6                <1> 	je	short namei_5
  4041                              <1> 		; beq 3b
  4042 000049D7 AE                  <1> 	scasb	
  4043                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  4044                              <1> 			      ; / char read from directory
  4045 000049D8 74E3                <1> 	je 	short namei_5
  4046                              <1> 		; beq 3b / branch if chars match
  4047                              <1> namei_10:
  4048 000049DA E972FFFFFF          <1>         jmp	namei_3 ; 2b
  4049                              <1> 		; br 2b / file names do not match go to next directory entry
  4050                              <1> namei_7: ; 3:
  4051 000049DF 81FF[EC6E0000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4052                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  4053 000049E5 7405                <1> 	je	short namei_8
  4054                              <1> 		; beq 3f
  4055                              <1> 	;mov 	ah, [edi]
  4056                              <1> 	;;inc 	edi 
  4057                              <1> 	;and 	ah, ah
  4058                              <1> 	;	; tstb (r3)+ /
  4059                              <1>         ; 18/10/2021
  4060 000049E7 F607FF              <1> 	test	byte [edi], 0FFh
  4061                              <1> 	; 08/01/2021
  4062 000049EA 75EE                <1> 	jnz	short namei_10 
  4063                              <1> 	;jnz	namei_3
  4064                              <1> 		; bne 2b
  4065                              <1> namei_8: ; 3
  4066 000049EC 892D[C06E0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  4067                              <1> 		; mov r2,u.namep / u.namep points to char 
  4068                              <1> 			       ; / following a / or nul
  4069                              <1> 	;mov	bx, [u.dirbuf]
  4070                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  4071                              <1> 				; / entry to r1
  4072 000049F2 20C0                <1> 	and 	al, al
  4073                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  4074                              <1> 		      ;  / if r4 = </> then go to next directory
  4075                              <1> 	;mov	ax, bx
  4076                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  4077                              <1>         ; 18/10/2021 (16 bit inode number in 32 bit register)
  4078 000049F4 0FB705[DC6E0000]    <1> 	movzx	eax, word [u.dirbuf] 
  4079                              <1> 	; 19/12/2021
  4080 000049FB E91CFFFFFF          <1> 	jmp	namei_9 ; eax = inode number
  4081                              <1> ;	jnz	namei_2 
  4082                              <1> ;		; bne 1b
  4083                              <1> ;	; AX = i-number of the file
  4084                              <1> ;;;nig:
  4085                              <1> ;	retn
  4086                              <1> 		; tst (r0)+ / gives non-error return
  4087                              <1> ;;nib:
  4088                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  4089                              <1> 		       ; ax = 0 -> file not found 
  4090                              <1> ;;	stc	; 27/05/2013
  4091                              <1> ;;	retn
  4092                              <1> 		; rts r0
  4093                              <1> 
  4094                              <1> trans_addr_nmbp:
  4095                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4096                              <1> 	; 18/10/2015
  4097                              <1> 	; 12/10/2015
  4098 00004A00 8B2D[C06E0000]      <1> 	mov 	ebp, [u.namep]
  4099                              <1> trans_addr_nm: 
  4100                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4101                              <1> 	; Convert virtual (pathname) address to physical address
  4102                              <1> 	; (Retro UNIX 386 v1 feature only !)
  4103                              <1> 	; 18/10/2015
  4104                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  4105                              <1> 	; 02/07/2015
  4106                              <1> 	; 17/06/2015
  4107                              <1> 	; 16/06/2015
  4108                              <1> 	;
  4109                              <1> 	; INPUTS: 
  4110                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  4111                              <1> 	;	[u.pgdir] = user's page directory
  4112                              <1> 	; OUTPUT:
  4113                              <1> 	;       esi = physical address of the pathname
  4114                              <1> 	;	ecx = remain byte count in the page
  4115                              <1> 	;
  4116                              <1> 	; (Modified registers: EBX, ECX, EDX, ESI) ; 18/10/2021
  4117                              <1> 	;
  4118                              <1> 
  4119                              <1> 	; 18/10/2021
  4120 00004A06 29C9                <1> 	sub	ecx, ecx
  4121                              <1> 	;
  4122                              <1>         ;cmp	dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  4123 00004A08 390D[086F0000]      <1> 	cmp	[u.ppgdir], ecx ; 0 ; 18/10/2021
  4124 00004A0E 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  4125                              <1> 				     ; it is already physical address
  4126 00004A10 50                  <1>    	push	eax	
  4127 00004A11 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  4128 00004A13 E83CE8FFFF          <1>        	call	get_physical_addr ; get physical address
  4129 00004A18 7204                <1> 	jc	short tr_addr_nm_err
  4130                              <1> 	; 18/10/2015
  4131                              <1> 	; eax = physical address 
  4132                              <1> 	; ecx = remain byte count in page (1-4096) ; 18/10/2021
  4133                              <1> 		; 12/10/2015 (cx = [u.pncount])
  4134 00004A1A 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  4135 00004A1C 58                  <1> 	pop	eax 
  4136 00004A1D C3                  <1> 	retn
  4137                              <1> 
  4138                              <1> tr_addr_nm_err:
  4139 00004A1E A3[186F0000]        <1> 	mov	[u.error], eax
  4140                              <1> 	;pop 	eax
  4141 00004A23 E984F1FFFF          <1> 	jmp	error
  4142                              <1> 
  4143                              <1> trans_addr_nmk:
  4144                              <1> 	; 12/10/2015
  4145                              <1> 	; 02/07/2015
  4146 00004A28 8B35[C06E0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  4147                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  4148                              <1> 	; 18/10/2021
  4149 00004A2E B510                <1> 	mov	ch, PAGE_SIZE/256
  4150 00004A30 C3                  <1> 	retn
  4151                              <1> 
  4152                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  4153                              <1> chk_dir:
  4154                              <1> 	; 12/06/2021
  4155                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  4156                              <1> 	; Check for directory inode
  4157                              <1> 
  4158 00004A31 8A0D[416B0000]      <1> 	mov	cl, [i.flgs+1]
  4159                              <1> 	;test	cl, 80h ; IFREG ; 80h
  4160                              <1> 	;jz	short chk_dir_err ; not a regular file ! (device!?)
  4161                              <1> 	;and	cl, 40h ; IFDIR ; 40h
  4162                              <1> 	;jz	short chk_dir_err ; not a sub directory !
  4163 00004A37 D0E1                <1> 	shl	cl, 1 ; 80h (IFREG flag) -> cf = 1
  4164 00004A39 7305                <1> 	jnc	short chk_dir_err ; not a regular file ! (device!?)
  4165 00004A3B D0E1                <1> 	shl	cl, 1 ; 40h (IFDIR flag) -> cf = 1
  4166 00004A3D 7301                <1> 	jnc	short chk_dir_err ; not a sub directory !
  4167                              <1> 	; 12/06/2021
  4168 00004A3F C3                  <1> 	retn
  4169                              <1> chk_dir_err:
  4170 00004A40 C705[186F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4170 00004A48 0000                <1>
  4171 00004A4A E95DF1FFFF          <1> 	jmp	error
  4172                              <1> 
  4173                              <1> 	; 08/01/2022
  4174                              <1> 	; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode)
  4175                              <1> syschdir:
  4176                              <1> 	; / makes the directory specified in the argument
  4177                              <1> 	; / the current directory
  4178                              <1> 	;
  4179                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.2)
  4180                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4181                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  4182                              <1> 	;
  4183                              <1> 	; 'syschdir' makes the directory specified in its argument
  4184                              <1> 	; the current working directory.
  4185                              <1> 	;
  4186                              <1> 	; Calling sequence:
  4187                              <1> 	;	syschdir; name
  4188                              <1> 	; Arguments:
  4189                              <1> 	;	name - address of the path name of a directory
  4190                              <1> 	;	       terminated by nul byte.	
  4191                              <1> 	; Inputs: -
  4192                              <1> 	; Outputs: -
  4193                              <1> 	; ...............................................................
  4194                              <1> 	;				
  4195                              <1> 	; Retro UNIX 8086 v1 modification:
  4196                              <1> 	;	 The user/application program puts address of 
  4197                              <1> 	;	 the path name in BX register as 'syschdir' 
  4198                              <1> 	; 	 system call argument.
  4199                              <1> 
  4200 00004A4F 891D[C06E0000]      <1> 	mov	[u.namep], ebx
  4201                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  4202 00004A55 E888FEFFFF          <1> 	call	namei
  4203                              <1> 		; jsr r0,namei / find its i-number
  4204                              <1> 	;jc	error
  4205                              <1> 		; br error3
  4206 00004A5A 730F                <1> 	jnc	short syschdir0
  4207                              <1> 	; 'directory not found !' error
  4208 00004A5C C705[186F0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  4208 00004A64 0000                <1>
  4209 00004A66 E941F1FFFF          <1> 	jmp	error
  4210                              <1> syschdir0:
  4211                              <1> 	; 08/01/2022
  4212 00004A6B 66BA0001            <1> 	mov	dx, 100h  ; read access ; IREAD (100h)
  4213 00004A6F E8E6080000          <1> 	call	access
  4214                              <1> 		; jsr r0,access; 2 / get i-node into core
  4215                              <1> 	
  4216                              <1> 	; 01/01/2022 (runix v2 fs inode flag)
  4217 00004A74 F605[416B0000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  4218 00004A7B 7409                <1> 	jz	short syschdir2 ; no, error!
  4219 00004A7D F605[416B0000]40    <1> 	test	byte [i.flgs+1], 40h ; directory flag ?
  4220                              <1> 	;test	word [i.flgs], 4000h
  4221                              <1> 		; bit $40000,i.flgs / is it a directory?
  4222                              <1> 	;jz	error 
  4223                              <1> 		; beq error3 / no error
  4224 00004A84 750F                <1> 	jnz	short syschdir1
  4225                              <1> syschdir2:
  4226 00004A86 C705[186F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4226 00004A8E 0000                <1>
  4227 00004A90 E917F1FFFF          <1> 	jmp	error
  4228                              <1> syschdir1:
  4229 00004A95 66A3[A86E0000]      <1> 	mov	[u.cdir], ax
  4230                              <1> 		; mov r1,u.cdir / move i-number to users 
  4231                              <1> 			      ; / current directory
  4232                              <1> 	;mov	ax, [cdev]
  4233                              <1> 	;mov	[u.cdrv], ax
  4234                              <1> 	; 08/01/2022
  4235 00004A9B A0[856E0000]        <1> 	mov	al, [cdev]
  4236 00004AA0 A2[AC6E0000]        <1> 	mov	[u.cdrv], al
  4237                              <1> 		; mov cdev,u.cdev / move its device to users 
  4238                              <1> 			        ; / current device
  4239 00004AA5 E922F1FFFF          <1> 	jmp	sysret
  4240                              <1> 		; br sysret3
  4241                              <1> 
  4242                              <1> syschmod: ; < change mode of file >
  4243                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4244                              <1> 	; 01/05/2021
  4245                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4246                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4247                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4248                              <1> 	;
  4249                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4250                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4251                              <1> 	; changed to 'mode'.
  4252                              <1> 	;
  4253                              <1> 	; Calling sequence:
  4254                              <1> 	;	syschmod; name; mode
  4255                              <1> 	; Arguments:
  4256                              <1> 	;	name - address of the file name
  4257                              <1> 	;	       terminated by null byte.
  4258                              <1> 	;	mode - (new) mode/flags < attributes >
  4259                              <1> 	;	
  4260                              <1> 	; Inputs: -
  4261                              <1> 	; Outputs: -
  4262                              <1> 	; ...............................................................
  4263                              <1> 	;				
  4264                              <1> 	; Retro UNIX 8086 v1 modification: 
  4265                              <1> 	;       'syschmod' system call has two arguments; so,
  4266                              <1> 	;	* 1st argument, name is pointed to by BX register
  4267                              <1> 	;	* 2nd argument, mode is in CX register
  4268                              <1> 	;
  4269                              <1> 	; Mode bits (Flags):
  4270                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4271                              <1> 	;	bit 14 - directory flag (4000h)
  4272                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4273                              <1> 	;	bit 12 - large file flag (1000h)
  4274                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4275                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4276                              <1> 	;	bit 4 - executable flag (10h)
  4277                              <1> 	;	bit 3 - read permission for owner (08h)
  4278                              <1> 	;	bit 2 - write permission for owner (04h)
  4279                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4280                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4281                              <1> 
  4282                              <1> 	; 01/05/2021 (07/02/2020)
  4283                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  4284                              <1> 	; 	bit 15 - IFREG - regular file (8000h)
  4285                              <1> 	;	bit 14 - IFDIR - directory (4000h)
  4286                              <1> 	;	bit 13 - IRSVD - 0 - reserved/mounted bit (2000h)
  4287                              <1> 	; 	bit 12 - ILARG - large file addressing bit (1000h)
  4288                              <1> 	; 	bit 11 - ISUID - set user id on exec (800h)
  4289                              <1> 	;	bit 10 - ISGID - set group id on exec (400h)
  4290                              <1> 	; 	bit  9 - IEXTT - 0 - use extents (200h)
  4291                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4292                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4293                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4294                              <1> 	; 	bit  5 - read, group (20h)
  4295                              <1> 	; 	bit  4 - write, group (10h)
  4296                              <1> 	; 	bit  3 - execute, group (08h)
  4297                              <1> 	;	bit  2 - read, others (04h)
  4298                              <1> 	; 	bit  1 - write, others (02h)
  4299                              <1> 	; 	bit  0 - execute, others (01h)
  4300                              <1> 	;
  4301                              <1> 	; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  4302                              <1> 	;	bit 15 - IFREG - 0 - device file (8000h)
  4303                              <1> 	; 	bit 14 - IFBLK - block device (4000h)
  4304                              <1> 	; 	bit 13 - IFCHR - 1 - character special (2000h)
  4305                              <1> 	;	bit 12 - IFIFO - fifo special (1000h)
  4306                              <1> 	; 	bit 11 - IPIPE - pipe special (800h)
  4307                              <1> 	;	bit 10 - IREDIR - redirected (400h)
  4308                              <1> 	;	bit  9 - IEXTR - external device driver (200h)
  4309                              <1> 	;	bit  8 - IREAD - read, owner (100h)
  4310                              <1> 	;	bit  7 - IWRITE - write, owner (80h)
  4311                              <1> 	;	bit  6 - IEXEC - execute, owner (40h)
  4312                              <1> 	; 	bit  5 - read, group (20h)
  4313                              <1> 	; 	bit  4 - write, group (10h)
  4314                              <1> 	; 	bit  3 - execute, group (08h)
  4315                              <1> 	;	bit  2 - read, others (04h)
  4316                              <1> 	; 	bit  1 - write, others (02h)
  4317                              <1> 	; 	bit  0 - execute, others (01h)
  4318                              <1> 
  4319                              <1> 	; / name; mode
  4320 00004AAA E870000000          <1> 	call	isown
  4321                              <1> 		;jsr r0,isown / get the i-node and check user status
  4322                              <1> 
  4323                              <1> 	; 25/05/2020
  4324                              <1> 	; AL = new mode (return form 'isown', ecx -> eax)
  4325                              <1> 
  4326                              <1> 	;test	word [i.flgs], 4000h
  4327                              <1> 	;	; bit $40000,i.flgs / directory?
  4328                              <1> 	;jz	short syschmod1
  4329                              <1> 	;	; beq 2f / no
  4330                              <1> 	;; AL = (new) mode
  4331                              <1> 	;and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4332                              <1> 	;	; bic $60,r2 / su & ex / yes, clear set user id and 
  4333                              <1> 	;		   ; / executable modes
  4334                              <1> 
  4335                              <1> 	; 01/05/2021
  4336                              <1> 	; AX = new mode (9 bits for devices or 12 bits files)
  4337 00004AAF 8A15[416B0000]      <1> 	mov	dl, [i.flgs+1]
  4338                              <1> 	; 09/01/2022
  4339 00004AB5 F6C280              <1> 	test	dl, 80h ; regular file
  4340 00004AB8 7416                <1> 	jz	short syschmod1 ; device file
  4341 00004ABA F6C240              <1> 	test	dl, 40h ; directory
  4342 00004ABD 7511                <1> 	jnz	short syschmod1
  4343                              <1> 	; regular file
  4344 00004ABF 6625FF0D            <1> 	and	ax, 0DFFh ; clear bit 9, 12-15 (of new mode)
  4345                              <1> 	; clear bit 8,10,11 of current mode/flags
  4346 00004AC3 80E2F2              <1> 	and	dl, 0F2h ; and dl, 11110010b
  4347                              <1> syschmod0:
  4348 00004AC6 08D4                <1> 	or	ah, dl
  4349 00004AC8 66A3[406B0000]      <1> 	mov	[i.flgs], ax	
  4350 00004ACE EB3E                <1> 	jmp	short syschmod2
  4351                              <1> syschmod1: 
  4352                              <1> 	; device or directory	
  4353 00004AD0 6625B601            <1> 	and	ax, 1B6h ; clear bit 9-15 & bit 0,3,6 (EXEC bits)
  4354                              <1> 	; clear bit 8 (IREAD) of current mode/flags
  4355                              <1> 	;	 (dl contains flag bits 8-15)
  4356 00004AD4 80E2FE              <1> 	and	dl, ~1 ; and dl, 11111110b 
  4357 00004AD7 EBED                <1> 	jmp	short syschmod0
  4358                              <1> 
  4359                              <1> ;syschmod1: ; 2:
  4360                              <1> 	;mov	[i.flgs], al	
  4361                              <1> 	;	; movb r2,i.flgs / move remaining mode to i.flgs
  4362                              <1> 
  4363                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4364                              <1> 	;mov	byte [imodx], 1 ; (flag means file data is same
  4365                              <1> 	;			;  but inode's itself has been modified)
  4366                              <1> 	;call	setimod
  4367                              <1> 	;jmp	sysret
  4368                              <1> 
  4369                              <1> 	; 25/05/2020
  4370                              <1> 	;jmp	short syschmod2
  4371                              <1> 
  4372                              <1> syschown: ; < change owner of file >
  4373                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4374                              <1> 	; 01/05/2021
  4375                              <1> 	;	(change owner and group ID of file)
  4376                              <1> 	; 02/04/2021
  4377                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4378                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4379                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4380                              <1> 	;
  4381                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4382                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4383                              <1> 	; changed to 'owner'
  4384                              <1> 	;
  4385                              <1> 	; Calling sequence:
  4386                              <1> 	;	syschown; name; owner
  4387                              <1> 	; Arguments:
  4388                              <1> 	;	name - address of the file name
  4389                              <1> 	;	       terminated by null byte.
  4390                              <1> 	;	owner - (new) owner (number/ID)
  4391                              <1> 	;	
  4392                              <1> 	; Inputs: -
  4393                              <1> 	; Outputs: -
  4394                              <1> 	; ...............................................................
  4395                              <1> 	;				
  4396                              <1> 	; Retro UNIX 8086 v1 modification: 
  4397                              <1> 	;       'syschown' system call has two arguments; so,
  4398                              <1> 	;	* 1st argument, name is pointed to by BX register
  4399                              <1> 	;	* 2nd argument, owner number is in CX register
  4400                              <1> 	;
  4401                              <1> 	; / name; owner
  4402 00004AD9 E841000000          <1> 	call	isown
  4403                              <1> 		; jsr r0,isown / get the i-node and check user status
  4404                              <1> 	
  4405                              <1> 	; 25/05/2020
  4406                              <1> 	; AL = owner number (return form 'isown', ecx -> eax)
  4407                              <1> 	; 02/04/2021
  4408                              <1> 	; AX = owner number
  4409                              <1> 	; 01/05/2021
  4410                              <1> 	; byte 2 of EAX is group number
  4411                              <1> 
  4412                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013 
  4413                              <1> 	;	; tstb u.uid / super user
  4414                              <1> 	;jz	short syschown1
  4415                              <1> 	;	; beq 2f / yes, 2f
  4416 00004ADE 66833D[F66E0000]00  <1> 	cmp	word [u.uid], 0
  4417 00004AE6 7418                <1> 	jz	short syschown1
  4418                              <1> 
  4419                              <1> 	;test	byte [i.flgs], 20h ; 32
  4420                              <1> 	;	; bit $40,i.flgs / no, set userid on execution?
  4421                              <1> 	;;jnz	error
  4422                              <1> 	;	; bne 3f / yes error, could create Trojan Horses
  4423                              <1> 	;jz	short syschown1
  4424                              <1> 	; 01/05/2021
  4425                              <1> 	; check set user id on execution flag
  4426                              <1> 	; (protection against Trojan Horses)
  4427                              <1> 
  4428                              <1> 	; ((Note: UNIX v7 x86 'chown' source code in 'sys4.c'
  4429                              <1> 	;        does not contain this protection)) 
  4430                              <1> 
  4431                              <1> 	; 09/01/2022
  4432 00004AE8 F605[416B0000]08    <1> 	test	byte [i.flgs+1], 08h ; ISUID ; RUNIX v2 inode flags  	
  4433 00004AEF 740F                <1> 	jz	short syschown1
  4434                              <1> 
  4435                              <1> 	; 'permission denied !'
  4436 00004AF1 C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4436 00004AF9 0000                <1>
  4437 00004AFB E9ACF0FFFF          <1> 	jmp	error
  4438                              <1> syschown1: ; 2:
  4439                              <1> 	;; AL = owner (number/ID)
  4440                              <1> 	;mov	[i.uid], al ; 23/06/2015
  4441                              <1> 	;	;  movb	r2,i.uid / no, put the new owners id 
  4442                              <1> 	;		       ; / in the i-node
  4443                              <1> 	; 02/04/2021 (Retro UNIX 386 v2)
  4444                              <1> 	; AX = owner number
  4445 00004B00 66A3[446B0000]      <1> 	mov	[i.uid], ax ; owner
  4446                              <1> 	; 01/05/2021 (Retro UNIX 386 v2)
  4447 00004B06 C1E810              <1> 	shr	eax, 16
  4448 00004B09 A2[466B0000]        <1> 	mov	[i.gid], al ; group
  4449                              <1> syschown2:
  4450                              <1> 	; 25/05/2020 - Retro UNIX 386 v2
  4451                              <1> syschmod2:
  4452                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4453 00004B0E C605[976E0000]01    <1> 	mov	byte [imodx], 1	; (flag means file data is same
  4454                              <1> 			      ;  but inode's itself has been modified)
  4455 00004B15 E8F5080000          <1> 	call	setimod ; 25/05/2020
  4456                              <1> 	
  4457 00004B1A E9ADF0FFFF          <1> 	jmp	sysret
  4458                              <1> 
  4459                              <1> 	; 1: 
  4460                              <1> 		; jmp sysret4
  4461                              <1> 	; 3:
  4462                              <1> 		; jmp	error
  4463                              <1> 
  4464                              <1> isown:
  4465                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4466                              <1> 	; 06/11/2021
  4467                              <1> 	; 12/06/2021
  4468                              <1> 	; 01/05/2021
  4469                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  4470                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4471                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4472                              <1> 	;
  4473                              <1> 	; 'isown' is given a file name (the 1st argument).
  4474                              <1> 	;  It find the i-number of that file via 'namei' 
  4475                              <1> 	;  then gets the i-node into core via 'iget'.
  4476                              <1> 	;  It then tests to see if the user is super user. 
  4477                              <1> 	;  If not, it checks to see if the user is owner of 
  4478                              <1> 	;  the file. If he is not an error occurs.
  4479                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4480                              <1> 	;  the inode has been modified and the 2nd argument of
  4481                              <1> 	;  the call is put in r2.
  4482                              <1> 	;
  4483                              <1> 	; INPUTS ->
  4484                              <1> 	;    arguments of syschmod and syschown calls
  4485                              <1> 	; OUTPUTS ->
  4486                              <1> 	;    u.uid - id of user
  4487                              <1> 	;    imod - set to a 1
  4488                              <1> 	;    r2 - contains second argument of the system call
  4489                              <1> 	;
  4490                              <1> 	;   ((AX=R2) output as 2nd argument)
  4491                              <1> 	;
  4492                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))
  4493                              <1> 	;
  4494                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4495                              <1> 	;; ! 2nd argument on top of stack !
  4496                              <1> 	;; 22/06/2015 - 32 bit modifications
  4497                              <1> 	;; 07/07/2013
  4498 00004B1F 891D[C06E0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4499 00004B25 51                  <1> 	push 	ecx ;* ; 2nd argument
  4500                              <1> 	;;
  4501 00004B26 E8B7FDFFFF          <1> 	call	namei
  4502                              <1> 		; jsr r0,namei / get its i-number
  4503                              <1>        ; Retro UNIX 8086 v1 modification !
  4504                              <1>        ; ax = 0 -> file not found 
  4505                              <1> 	;and	ax, ax
  4506                              <1> 	;jz	error
  4507                              <1> 	;jc	error ; 27/05/2013
  4508                              <1> 		; br error3
  4509 00004B2B 730F                <1> 	jnc	short isown1  ; 25/05/2020 (isown0 -> isown1)
  4510                              <1> 	; 'file not found !' error
  4511 00004B2D C705[186F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4511 00004B35 0000                <1>
  4512 00004B37 E970F0FFFF          <1> 	jmp	error
  4513                              <1> isown1:
  4514 00004B3C E82F070000          <1> 	call	iget
  4515                              <1> 		; jsr r0,iget / get i-node into core
  4516                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  4517                              <1> 	;; 06/11/2021
  4518                              <1> 	;jnc	short isown3
  4519                              <1> 	;mov	[u.error], eax
  4520                              <1> 	;jmp	error
  4521                              <1> ;isown3:
  4522                              <1> 	; check if it is super user ID
  4523                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4524 00004B41 66A1[F66E0000]      <1> 	mov	ax, [u.uid]
  4525 00004B47 6609C0              <1> 	or	ax, ax
  4526                              <1> 	;mov	al, [u.uid] ; 02/08/2013
  4527                              <1> 	;or	al, al
  4528                              <1> 		; tstb u.uid / super user?
  4529                              <1> 	; 12/06/2021
  4530 00004B4A 7425                <1> 	jz	short isown2 ; 25/05/2020 (isown1 -> isown2)
  4531                              <1> 		; beq 1f / yes, branch
  4532                              <1> 	
  4533                              <1> 	; check user ID	(if same with file's owner)
  4534 00004B4C 663B05[446B0000]    <1> 	cmp	ax, [i.uid] ; 09/01/2022
  4535                              <1> 	;cmp	al, [i.uid]
  4536                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4537                              <1> 				 ; / the file
  4538                              <1> 	;jne	error
  4539                              <1> 		; beq 1f / yes
  4540                              <1> 		; jmp error3 / no, error
  4541                              <1> 	;je	short isown2 ; 25/05/2020
  4542                              <1> 	; 01/05/2021
  4543 00004B53 750D                <1> 	jne	short isown_err
  4544                              <1> 
  4545                              <1> 	; 01/05/2021
  4546                              <1> 	;mov	ax, [u.uid]
  4547                              <1> 	;or	ax, ax
  4548                              <1> 	;jz	short isown2 
  4549                              <1> 	;cmp	ax, [i.uid]
  4550                              <1> 	;;je	short isown2
  4551                              <1> 	;jne	short isown_err
  4552                              <1> 
  4553                              <1> 	; 01/05/2021
  4554                              <1> 	; ((Note: UNIX v7 x86 'chown', 'chmod' procedures
  4555                              <1> 	;    and their sub procedures do not check group ID))
  4556                              <1> 	; (('sys4.c', 'fio.c'))
  4557                              <1> 
  4558                              <1> 	; 01/05/2021
  4559                              <1> 	; check group ID (if same with group of file's owner)
  4560 00004B55 A0[FA6E0000]        <1> 	mov	al, [u.gid]
  4561 00004B5A 3A05[466B0000]      <1> 	cmp	al, [i.gid]
  4562 00004B60 740F                <1> 	je	short isown2
  4563                              <1> isown_err:
  4564 00004B62 C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER ; 11
  4564 00004B6A 0000                <1>
  4565                              <1> 			; 'permission denied !' error
  4566 00004B6C E93BF0FFFF          <1> 	jmp	error
  4567                              <1> 
  4568                              <1> 	; 25/05/2020
  4569                              <1> ;isown2: ; 1:
  4570                              <1> ;	call	setimod
  4571                              <1> ;		; jsr r0,setimod / indicates 
  4572                              <1> ;		;	       ; / i-node has been modified
  4573                              <1> isown2: 
  4574                              <1> 	; 25/05/2020
  4575 00004B71 58                  <1> 	pop	eax ;* ; 2nd argument
  4576                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4577                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4578 00004B72 C3                  <1> 	retn
  4579                              <1> 
  4580                              <1> ;;arg:  ; < get system call arguments >
  4581                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4582                              <1> 	; of form:
  4583                              <1> 	;	sys 'routine' ; arg1
  4584                              <1> 	;		or
  4585                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4586                              <1> 	;		or
  4587                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4588                              <1> 	;	
  4589                              <1> 	; INPUTS ->
  4590                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4591                              <1> 	;	This pointers's value is actually the value of
  4592                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4593                              <1> 	;	made to process the sys instruction
  4594                              <1> 	;    r0 - contains the return address for the routine
  4595                              <1> 	;	that called arg. The data in the word pointer 
  4596                              <1> 	;	to by the return address is used as address
  4597                              <1> 	;	in which the extracted argument is stored
  4598                              <1> 	;    	
  4599                              <1> 	; OUTPUTS ->
  4600                              <1> 	;    'address' - contains the extracted argument 
  4601                              <1> 	;    u.sp+18 - is incremented by 2 
  4602                              <1> 	;    r1 - contains the extracted argument
  4603                              <1> 	;    r0 - points to the next instruction to be
  4604                              <1> 	;	 executed in the calling routine.
  4605                              <1> 	;
  4606                              <1>   
  4607                              <1> 	; mov u.sp,r1
  4608                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4609                              <1> 			; / into argument of arg2
  4610                              <1> 	; add $2,18.(r1) / point pc on stack 
  4611                              <1> 			      ; / to next system argument
  4612                              <1> 	; rts r0
  4613                              <1> 
  4614                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4615                              <1> 	; 'arg2' takes first argument in system call
  4616                              <1> 	;  (pointer to name of the file) and puts it in location
  4617                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4618                              <1> 	;  and on top of the stack
  4619                              <1> 	;	
  4620                              <1> 	; INPUTS ->
  4621                              <1> 	;    u.sp, r0
  4622                              <1> 	;    	
  4623                              <1> 	; OUTPUTS ->
  4624                              <1> 	;    u.namep
  4625                              <1> 	;    u.off 
  4626                              <1> 	;    u.off pushed on stack
  4627                              <1> 	;    r1
  4628                              <1> 	;
  4629                              <1> 
  4630                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4631                              <1> 				; / first arg in sys call
  4632                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4633                              <1> 				; / second arg in sys call
  4634                              <1> 	; mov r0,r1 / r0 points to calling routine
  4635                              <1> 	; mov (sp),r0 / put operation code back in r0
  4636                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4637                              <1> 			; / on stack
  4638                              <1> 	; jmp (r1) / return to calling routine
  4639                              <1> 
  4640                              <1> systime: ; / get time of year
  4641                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4642                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4643                              <1> 	;
  4644                              <1> 	; 20/06/2013
  4645                              <1> 	; 'systime' gets the time of the year.
  4646                              <1> 	; The present time is put on the stack.
  4647                              <1> 	;
  4648                              <1> 	; Calling sequence:
  4649                              <1> 	;	systime
  4650                              <1> 	; Arguments: -
  4651                              <1> 	;	
  4652                              <1> 	; Inputs: -
  4653                              <1> 	; Outputs: sp+2, sp+4 - present time
  4654                              <1> 	; ...............................................................
  4655                              <1> 	;	
  4656                              <1> 	; Retro UNIX 8086 v1 modification: 
  4657                              <1> 	;       'systime' system call will return to the user
  4658                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4659                              <1> 	;
  4660                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4661                              <1> 	;	system call for PC compatibility !!		 	
  4662                              <1> 
  4663 00004B73 E851EBFFFF          <1> 	call 	epoch
  4664 00004B78 A3[A46E0000]        <1> 	mov 	[u.r0], eax
  4665                              <1> 		; mov s.time,4(sp)
  4666                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4667                              <1> 				   ; / on the stack
  4668                              <1> 		; br sysret4
  4669 00004B7D E94AF0FFFF          <1> 	jmp	sysret 
  4670                              <1> 
  4671                              <1> sysstime: ; / set time
  4672                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4673                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4674                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4675                              <1> 	;
  4676                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4677                              <1> 	;
  4678                              <1> 	; Calling sequence:
  4679                              <1> 	;	sysstime
  4680                              <1> 	; Arguments: -
  4681                              <1> 	;	
  4682                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4683                              <1> 	; Outputs: -
  4684                              <1> 	; ...............................................................
  4685                              <1> 	;	
  4686                              <1> 	; Retro UNIX 8086 v1 modification: 
  4687                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4688                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4689                              <1> 	; 
  4690                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4691                              <1> 	;	to get sysstime system call arguments from the user;
  4692                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4693                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4694                              <1> 	;
  4695                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4696                              <1> 	;	system call for PC compatibility !!	
  4697                              <1> 
  4698                              <1> 	; 09/01/2022 (Retro UNIX 386 v2 fs inode structure)
  4699 00004B82 66833D[F66E0000]00  <1> 	cmp	word [u.uid], 0 ; 16 bit user ID
  4700                              <1> 	;cmp	byte [u.uid], 0
  4701                              <1> 		; tstb u.uid / is user the super user
  4702                              <1> 	;ja	error
  4703                              <1> 		; bne error4 / no, error
  4704 00004B8A 760F                <1> 	jna	short systime1
  4705                              <1> 	; 'permission denied !'
  4706 00004B8C C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4706 00004B94 0000                <1>
  4707 00004B96 E911F0FFFF          <1> 	jmp	error
  4708                              <1> systime1:
  4709                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4710                              <1> 	; EBX = unix (epoch) time (from user)
  4711 00004B9B 89D8                <1> 	mov	eax, ebx
  4712 00004B9D E8A7ECFFFF          <1> 	call 	set_date_time
  4713                              <1> 		; mov 4(sp),s.time
  4714                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4715 00004BA2 E925F0FFFF          <1> 	jmp	sysret
  4716                              <1> 		; br sysret4
  4717                              <1> 
  4718                              <1> 
  4719                              <1> ; temporary - 01/01/2022
  4720                              <1> %if 0
  4721                              <1> 
  4722                              <1> sysbreak:
  4723                              <1> 	; 18/10/2015
  4724                              <1> 	; 07/10/2015
  4725                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4726                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4727                              <1> 	;
  4728                              <1> 	; 'sysbreak' sets the programs break points. 
  4729                              <1> 	; It checks the current break point (u.break) to see if it is
  4730                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4731                              <1> 	; even address (if it was odd) and the area between u.break
  4732                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4733                              <1> 	; in u.break and control is passed to 'sysret'.
  4734                              <1> 	;
  4735                              <1> 	; Calling sequence:
  4736                              <1> 	;	sysbreak; addr
  4737                              <1> 	; Arguments: -
  4738                              <1> 	;	
  4739                              <1> 	; Inputs: u.break - current breakpoint
  4740                              <1> 	; Outputs: u.break - new breakpoint 
  4741                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4742                              <1> 	; ...............................................................
  4743                              <1> 	;	
  4744                              <1> 	; Retro UNIX 8086 v1 modification:
  4745                              <1> 	;	The user/application program puts breakpoint address
  4746                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4747                              <1> 	; 	(argument transfer method 1)
  4748                              <1> 	;
  4749                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4750                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4751                              <1> 	;  NOTE:
  4752                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4753                              <1> 	;	'u.break' address) of user's memory for original unix's
  4754                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4755                              <1> 
  4756                              <1> 		; mov u.break,r1 / move users break point to r1
  4757                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4758                              <1> 		; blos 1f / yes, 1f
  4759                              <1> 	; 23/06/2015
  4760                              <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4761                              <1> 	;and	ebp, ebp
  4762                              <1> 	;jz	short sysbreak_3 
  4763                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4764                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4765                              <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4766                              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4767                              <1> 	; 07/10/2015
  4768                              <1> 	mov	[u.break], ebx ; virtual address !!!
  4769                              <1> 	;
  4770                              <1> 	cmp	ebx, [edx] ; compare new break point with 
  4771                              <1> 			   ; with top of user's stack (virtual!)
  4772                              <1> 	jnb	short sysbreak_3
  4773                              <1> 		; cmp r1,sp / is it the same or higher 
  4774                              <1> 			  ; / than the stack?
  4775                              <1> 		; bhis 1f / yes, 1f
  4776                              <1> 	mov	esi, ebx
  4777                              <1> 	sub	esi, ebp ; new break point - old break point
  4778                              <1> 	jna	short sysbreak_3 
  4779                              <1> 	;push	ebx
  4780                              <1> sysbreak_1:
  4781                              <1> 	mov	ebx, ebp  
  4782                              <1> 	call	get_physical_addr ; get physical address
  4783                              <1> 	jc	tr_addr_nm_err
  4784                              <1> 	; 18/10/2015
  4785                              <1> 	mov	edi, eax 
  4786                              <1> 	sub	eax, eax ; 0
  4787                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4788                              <1> 	cmp	esi, ecx
  4789                              <1> 	jnb	short sysbreak_2
  4790                              <1> 	mov	ecx, esi
  4791                              <1> sysbreak_2:
  4792                              <1> 	sub	esi, ecx
  4793                              <1> 	add	ebp, ecx
  4794                              <1> 	rep 	stosb
  4795                              <1> 	or	esi, esi
  4796                              <1> 	jnz	short sysbreak_1
  4797                              <1> 	;
  4798                              <1> 		; bit $1,r1 / is it an odd address
  4799                              <1> 		; beq 2f / no, its even
  4800                              <1> 		; clrb (r1)+ / yes, make it even
  4801                              <1> 	; 2: / clear area between the break point and the stack
  4802                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4803                              <1> 		; bhis 1f / yes, quit
  4804                              <1> 		; clr (r1)+ / clear word
  4805                              <1> 		; br 2b / go back
  4806                              <1> 	;pop	ebx
  4807                              <1> sysbreak_3: ; 1:
  4808                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4809                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4810                              <1> 			; / in u.break (set new break point)
  4811                              <1> 		; br sysret4 / br sysret
  4812                              <1> 	jmp	sysret
  4813                              <1> 
  4814                              <1> maknod: 
  4815                              <1> 	; 10/01/2022
  4816                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  4817                              <1> 	; 06/11/2021 (Retro UNIX 386 v2)
  4818                              <1> 	; 15/08/2021
  4819                              <1> 	; 06/05/2021
  4820                              <1> 	; 02/05/2021
  4821                              <1> 	; 01/04/2021
  4822                              <1> 	; 27/03/2021
  4823                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  4824                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4825                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4826                              <1> 	;
  4827                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4828                              <1> 	; for this i-node in the current directory.
  4829                              <1> 	;
  4830                              <1> 	; INPUTS ->
  4831                              <1> 	;    r1 - contains mode
  4832                              <1> 	;    ii - current directory's i-number	
  4833                              <1> 	;    	
  4834                              <1> 	; OUTPUTS ->
  4835                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4836                              <1> 	;    i.flgs - flags in new i-node 
  4837                              <1> 	;    i.uid - filled with u.uid
  4838                              <1> 	;    i.nlks - 1 is put in the number of links
  4839                              <1> 	;    i.ctim - creation time
  4840                              <1> 	;    i.ctim+2 - modification time
  4841                              <1> 	;    imod - set via call to setimod
  4842                              <1> 	;	
  4843                              <1> 	; ((AX = R1)) input
  4844                              <1> 	;
  4845                              <1> 	; (Retro UNIX Prototype : 
  4846                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4847                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))
  4848                              <1> 
  4849                              <1> 	; 27/03/2021
  4850                              <1> 	; INPUT:
  4851                              <1>  	;	AX = mode
  4852                              <1> 	;
  4853                              <1> 	; ('maknod' is called by 'syscreat' and 'sysmkdir')
  4854                              <1> 	; (('syscreat' and 'sysmkdir' will set AX input))
  4855                              <1> 
  4856                              <1> 	; 27/03/2021
  4857                              <1> 	; Retro UNIX 386 v2 inode mode flags (ref: 'ux.s')
  4858                              <1> 	; for File Inode: (high byte)
  4859                              <1> 	;   IFREG - 1 = regular file (8000h)
  4860                              <1> 	;   IFDIR - 1 = directory (4000h)
  4861                              <1> 	;   IRSVD - 0 = reserved bit (2000h) ; Mounted flag for dirs
  4862                              <1> 	;   ILARG - large file addressing bit (1000h)
  4863                              <1> 	;   ISUID - set user id on exec (800h)
  4864                              <1> 	;   ISGID - set group id on exec (400h)
  4865                              <1> 	;   IEXTT - 1 = use extents (200h)
  4866                              <1> 	;   IREAD - read, owner (100h)
  4867                              <1> 	; for Device Inode: (high byte)
  4868                              <1> 	;   IFREG - 0 = device file (8000h)
  4869                              <1> 	;   IFBLK - 1 = block device (4000h)
  4870                              <1> 	;   IFCHR - character special (2000h) -always 1-
  4871                              <1> 	;   IFIFO - fifo special (1000h)
  4872                              <1> 	;   IPIPE - pipe special (800h) ; 07/02/2020
  4873                              <1> 	;   IREDIR - redirected (400h)  ; 07/02/2020
  4874                              <1> 	;   IEXTR - 1 = external device driver (200h)
  4875                              <1> 	;   IREAD - read, owner (100h)
  4876                              <1> 
  4877                              <1> 	;; / r1 contains the mode
  4878                              <1> 	;or 	ah, 80h	; 10000000b
  4879                              <1> 	;	; bis	$100000,r1 / allocate flag set
  4880                              <1> 
  4881                              <1> 	; high 3 bit will be checked here
  4882                              <1> 	; 	(ref: unix v7 x86 source, iget.c)
  4883                              <1> 
  4884                              <1> ;	; 27/03/2021
  4885                              <1> ;	test	ah, 0E0h ; 80h+40h+20h
  4886                              <1> ;	jnz	short maknod0	
  4887                              <1> ;
  4888                              <1> ;	; ('syscreat' clears ILARG & IEXTT bits)
  4889                              <1> ;	;and	ah, ~0Ch ; clear ILARG & IEXTT bits
  4890                              <1> ;	;	; user can set ISUID & ISGID bits
  4891                              <1> ;
  4892                              <1> ;	or	ah, 80h ; IFREG
  4893                              <1> ;maknod0:
  4894                              <1> 	push	eax ; ***** ; 27/03/2021 (32 bit push, pop)
  4895                              <1> 		; mov r1,-(sp) / put mode on stack
  4896                              <1> 	; 31/07/2013
  4897                              <1> 	;mov	ax, [ii] ; move current i-number to AX/r1
  4898                              <1> 	;	; mov ii,r1 / move current i-number to r1
  4899                              <1> 	;mov	dl, 1 ; owner flag mask
  4900                              <1> 	; 15/08/2021
  4901                              <1> 	;movzx	eax, word [ii] ; move current i-number to EAX
  4902                              <1> 	; 09/01/2022
  4903                              <1> 	mov	eax, [ii] ; move current i-number to EAX
  4904                              <1> 	; 25/03/2021
  4905                              <1> 	mov	dx, 80h	; IWRITE - write,owner
  4906                              <1> 	call	access	
  4907                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4908                              <1> 	; 15/08/2021
  4909                              <1> 	; NOTE: cpu will not return here if there is a permission error
  4910                              <1> 	;	(it will jump to 'error' address from/in 'access')
  4911                              <1> 	
  4912                              <1> 	push	eax ; **** ; 27/03/2021 (32 bit push, pop)
  4913                              <1> 		; mov r1,-(sp) / put i-number on stack
  4914                              <1> 	;mov	ax, 40
  4915                              <1> 	;	; mov $40.,r1 / r1 = 40
  4916                              <1> 	; 27/03/2021
  4917                              <1> 	xor	eax, eax
  4918                              <1> 	;;dec	ax ; 0FFFFh
  4919                              <1> 	; 15/08/2021
  4920                              <1> 	;dec	eax ; 0FFFFFFFFh
  4921                              <1> 	; 01/04/2021
  4922                              <1> ;maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4923                              <1> 	;;inc	ax
  4924                              <1> 	;	; inc r1 / r1 = r1 + 1
  4925                              <1> 	; 15/08/2021
  4926                              <1> 	;inc	eax
  4927                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  4928                              <1> 	; eax = 0 -> start from first free inode
  4929                              <1> 	; eax > 0 -> locate this inode on the inode map buffer
  4930                              <1> 	; NOTE:
  4931                              <1> 	; Retro UNIX 386 v2 'imap' is mostly different than v1 'imap'
  4932                              <1> 	; ('imap' will not check inode table)
  4933                              <1> 	call	imap
  4934                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4935                              <1> 			    ; /	inode map in r2 & m
  4936                              <1> 	; 09/01/2022
  4937                              <1> 	; (cpu will not return here if there would be an eror in imap)
  4938                              <1> 	; 15/08/2021
  4939                              <1> 	;jc	short maknod_err
  4940                              <1> 
  4941                              <1> 	; DX (MQ) has a 1 in the calculated bit position
  4942                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4943                              <1> 
  4944                              <1> 	; 06/11/2021
  4945                              <1> 	; ebp = superblock buffer address
  4946                              <1> 	; eax = inode number
  4947                              <1> 	; 10/01/2022
  4948                              <1> 	; [ebp+SB.IMapBuffer] = physical block/sector number
  4949                              <1> 	;		of current IMAP sector	
  4950                              <1> 
  4951                              <1> 	; 27/03/2021
  4952                              <1> 	; If cpu is here, there is not an error
  4953                              <1> 	; and EBX points to inode map buffer
  4954                              <1> 	; DL has 1 at bit position which is for free inode
  4955                              <1> 	; (E)AX = inode number
  4956                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4957                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  4958                              <1> 
  4959                              <1> 	; 15/08/2021
  4960                              <1> maknod1:
  4961                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4962                              <1> 	;	       Inode count must be checked here
  4963                              <1> 	; (Original UNIX v1 did not check inode count here !?)
  4964                              <1> 	test	[ebx], dl
  4965                              <1> 		; bitb mq,(r2) / is the i-node active
  4966                              <1> 	;jnz	short maknod1
  4967                              <1> 	;	; bne 1b / yes, try the next one
  4968                              <1> 	; 15/08/2021
  4969                              <1> 	jz	short maknod3 ; free inode (inactive inode)
  4970                              <1> maknod2:
  4971                              <1> 	inc	eax
  4972                              <1> 	call	imap_x ; next call to imap (bypass 1st call code)
  4973                              <1> 	; 10/01/2022
  4974                              <1> 	; (cpu will/would not return here 
  4975                              <1> 	;  if there is/was an error in 'imap_x')
  4976                              <1> 	;jnc	short maknod1
  4977                              <1> 	jmp	short maknod1
  4978                              <1> maknod_err:
  4979                              <1> 	; 15/08/2021
  4980                              <1> 	;pop	edx  ; two pops for stack alignment
  4981                              <1> 	;pop	edx  ; (may not be needed while jumping to 'error')
  4982                              <1> 	mov	[u.error], eax
  4983                              <1> 	jmp	error
  4984                              <1> maknod3:
  4985                              <1> 	; 10/01/2022
  4986                              <1> 	; ebp = superblock buffer address
  4987                              <1> 	; eax = (free) inode number
  4988                              <1> 	; [ebp+SB.IMapBuffer] = physical block/sector number
  4989                              <1> 	;		of current IMAP sector
  4990                              <1> 	; EBX = buffer address/offset for relevant alloc byte
  4991                              <1> 	;  DL has 1 at bit position which is for free inode
  4992                              <1> 	;
  4993                              <1> 	; ECX = byte offset from the (start of) inode map buffer
  4994                              <1> 
  4995                              <1> 	;mov	[ebp+SB.LastInode], eax ; (free) inode number
  4996                              <1> 
  4997                              <1> 	push	eax ; ***
  4998                              <1> 	push	ecx ; **
  4999                              <1> 	push	edx ; *
  5000                              <1> 
  5001                              <1> 	mov	eax, [ebp+SB.ImapBuffer]
  5002                              <1> 
  5003                              <1> 	call	wslot
  5004                              <1> 	; ebx = buffer data address (write operation bit is set)
  5005                              <1> 	; eax = physical sector number
  5006                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  5007                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  5008                              <1> 
  5009                              <1> 	;mov	[ebp+SB.ImapBuffer], ebx
  5010                              <1> 			; save inode map buffer address
  5011                              <1> 	pop	edx ; *
  5012                              <1> 	pop	ecx ; **
  5013                              <1> 	add	ebx, ecx ; + byte offset (for allocation bit pos)	
  5014                              <1> 
  5015                              <1> 	; set allocation bit (for this new inode) ; 10/01/2022 
  5016                              <1> 	or	[ebx], dl
  5017                              <1> 		; bisb mq,(r2) / no, make it active 
  5018                              <1> 			     ; / (put a 1 in the bit map)
  5019                              <1> 	;push	ebp ; @
  5020                              <1> 	call	dskwr ; writes the 1st buffer to sector
  5021                              <1> 		      ; (at the beginning/head of the buffer chain)
  5022                              <1> 	;pop	ebp ; @
  5023                              <1> 
  5024                              <1> 	; if we are here, buffer has been written to disk successfully 
  5025                              <1> 	; (otherwise cpu would jump to 'error' address)
  5026                              <1> 
  5027                              <1> 	; set superblock modified flag
  5028                              <1> 	mov	edx, smod
  5029                              <1> 	test	byte [cdev], 1 ; mounted device ?
  5030                              <1> 	jz	short maknod4 ; no, root device
  5031                              <1> 	; yes, mounted device
  5032                              <1> 	;mov	edx, mmod
  5033                              <1> 	inc	edx ; edx = offset mmod
  5034                              <1> maknod4: 
  5035                              <1> 	inc	byte [edx] ; superblock modified !
  5036                              <1> 
  5037                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5038                              <1> 	;;
  5039                              <1> 	;; 27/03/2021
  5040                              <1> 	;; (ref: 'UNIXHDCP.ASM', 'mak_nod', 18/01/2020)
  5041                              <1> 	;or	byte [smod], 2 ; inode map modified
  5042                              <1> 	;; 01/04/2021
  5043                              <1> 	;;or	byte [imapbuf_hdr+bufhdr.status], 2
  5044                              <1> 	;or	byte [imapbuf_hdr], 2 ; set modified flag bit
  5045                              <1> 	; 02/05/2021
  5046                              <1> 	;or	byte [esi+ldrv.b_status], 2 ; inode map modified
  5047                              <1> 	; 15/08/2021
  5048                              <1> 	; 06/05/2021
  5049                              <1> 	;or	byte [esi+ldrv.status], 2 ; inode map modified
  5050                              <1> 	;;or	byte [sysbuf_hdr], 2 ; set modified flag bit
  5051                              <1> 	
  5052                              <1> 	;mov	eax, [ebp+SB.LastInode] ; (free) inode number
  5053                              <1> 	;push	eax ; ***
  5054                              <1> 	mov	eax, [esp] ; ***
  5055                              <1> 	inc	eax ; next inode number 
  5056                              <1> 		    ; (free inode search start value)
  5057                              <1> 	mov	[ebp+SB.FirstFreeIno], eax
  5058                              <1> 	call	get_system_time
  5059                              <1> 		; eax = current time (as unix epoch time)
  5060                              <1> 	mov	[ebp+SB.ModifTime], eax
  5061                              <1> 	pop	eax ; *** ; inode number
  5062                              <1> 	;;
  5063                              <1> 	call	iget
  5064                              <1> 		; jsr r0,iget / get i-node into core
  5065                              <1> 	; 09/01/2022
  5066                              <1> 	;  (If cpu is here, there was/is not an error!)
  5067                              <1> 	; 06/11/2021
  5068                              <1> 	;jc	short maknod_err
  5069                              <1> 	
  5070                              <1> 	;test	word [i.flgs], 8000h 
  5071                              <1> 	;	; tst i.flgs / is i-node already allocated
  5072                              <1> 	;jnz	short maknod1	
  5073                              <1> 	;	; blt 1b / yes, look for another one
  5074                              <1> 	; 27/03/2021
  5075                              <1> 	; (Retro UNIX 386 v2 inode flags) 
  5076                              <1> 	test	byte [i.flgs+1], 0E0h ; 80h+40h+20h
  5077                              <1> 	;jnz	short maknod1 ; i-node already allocated
  5078                              <1> 	;		      ; (as it is in inode table)
  5079                              <1> 	; 15/08/2021
  5080                              <1> 	jnz	short maknod2 ; defective inode map !?
  5081                              <1> 
  5082                              <1> 	; AX = free inode number
  5083                              <1> 	mov	[u.dirbuf], ax
  5084                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  5085                              <1> 	pop	eax ; **** ; 27/03/2021 (32 bit push, pop)
  5086                              <1> 		; mov (sp)+,r1 / get current i-number back
  5087                              <1> 	call	iget
  5088                              <1> 		; jsr r0,iget / get i-node in core
  5089                              <1> 	; 09/01/2022
  5090                              <1> 	; 06/11/2021
  5091                              <1> 	;jc	short maknod_err
  5092                              <1> 
  5093                              <1> 	call	mkdir
  5094                              <1> 		; jsr r0,mkdir / make a directory entry 
  5095                              <1> 			     ; / in current directory
  5096                              <1> 	; 09/01/2022
  5097                              <1> 	;  (If cpu is here, there was/is not an error in 'mkdir'!)
  5098                              <1> 	; 06/11/2021
  5099                              <1> 	;jc	short maknod_err
  5100                              <1> 	
  5101                              <1> 	; (eax = 0)
  5102                              <1> 	;movzx	eax, [u.difbuf] ; 06/11/2021
  5103                              <1> 	mov	ax, [u.dirbuf]
  5104                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  5105                              <1> 	call	iget
  5106                              <1> 		; jsr r0,iget / get it into core
  5107                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  5108                              <1> 	; 09/01/2022
  5109                              <1> 	; 06/11/2021
  5110                              <1> 	;jc	short maknod_err
  5111                              <1> 
  5112                              <1> 	;mov	ecx, 8
  5113                              <1> 	; 27/03/2021
  5114                              <1> 	xor	ecx, ecx 
  5115                              <1> 	mov	cl, 16 ; 64 bit inodes
  5116                              <1> 	xor	eax, eax ; 0
  5117                              <1> 	mov	edi, inode 
  5118                              <1> 	rep	stosd
  5119                              <1> 	;
  5120                              <1> 	;pop	word [i.flgs]
  5121                              <1> 	;	; mov (sp)+,i.flgs / fill flags
  5122                              <1> 	; 27/03/2021 (32 bit push, pop)
  5123                              <1> 	pop	eax ; *****
  5124                              <1> 	mov	[i.flgs], ax
  5125                              <1> 
  5126                              <1> 	;mov 	cl, [u.uid] ; 02/08/2013
  5127                              <1> 	;mov 	[i.uid], cl
  5128                              <1> 	;	; movb u.uid,i.uid / user id
  5129                              <1> 	; 15/08/2021
  5130                              <1> 	; 27/03/2021
  5131                              <1> 	mov	cl, [u.gid] ; 8 bit group ID ; 15/08/2021
  5132                              <1> 	mov	[i.gid], cl 	
  5133                              <1> 	mov	cx, [u.uid] ; 16 bit user ID
  5134                              <1> 	mov	[i.uid], cx	
  5135                              <1> 
  5136                              <1> 	mov     byte [i.nlks], 1
  5137                              <1> 		; movb $1,i.nlks / 1 link
  5138                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  5139                              <1> 	;mov	eax, [s.time]
  5140                              <1> 	;mov 	[i.ctim], eax
  5141                              <1> 	 	; mov s.time,i.ctim / time created
  5142                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  5143                              <1> 	; Retro UNIX 8086 v1 modification !
  5144                              <1> 	; i.ctime=0, i.ctime+2=0 and
  5145                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  5146                              <1> 	;call	setimod
  5147                              <1> 	;	; jsr r0,setimod / set modified flag
  5148                              <1> 	;retn
  5149                              <1> 	;	; rts r0 / return
  5150                              <1> 	; 27/03/2021
  5151                              <1> 	jmp	setimod
  5152                              <1> 
  5153                              <1> %endif
  5154                              <1> 
  5155                              <1> sysseek: ; / moves read write pointer in an fsp entry
  5156                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5157                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5158                              <1> 	;
  5159                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  5160                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  5161                              <1> 	; The file descriptor refers to a file open for reading or
  5162                              <1> 	; writing. The read (or write) pointer is set as follows:
  5163                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  5164                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  5165                              <1> 	;	  current location plus offset.
  5166                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  5167                              <1> 	;	  size of file plus offset.
  5168                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  5169                              <1> 	;
  5170                              <1> 	; Calling sequence:
  5171                              <1> 	;	sysseek; offset; ptrname
  5172                              <1> 	; Arguments:
  5173                              <1> 	;	offset - number of bytes desired to move 
  5174                              <1> 	;		 the r/w pointer
  5175                              <1> 	;	ptrname - a switch indicated above
  5176                              <1> 	;
  5177                              <1> 	; Inputs: r0 - file descriptor 
  5178                              <1> 	; Outputs: -
  5179                              <1> 	; ...............................................................
  5180                              <1> 	;	
  5181                              <1> 	; Retro UNIX 8086 v1 modification: 
  5182                              <1> 	;       'sysseek' system call has three arguments; so,
  5183                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  5184                              <1> 	;	* 2nd argument, offset is in CX register
  5185                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  5186                              <1> 	;	
  5187                              <1> 
  5188 00004BA7 E822000000          <1> 	call	seektell
  5189                              <1> 	; AX = u.count
  5190                              <1> 	; BX = *u.fofp
  5191                              <1> 		; jsr r0,seektell / get proper value in u.count
  5192                              <1> 		; add u.base,u.count / add u.base to it
  5193 00004BAC 0305[C86E0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  5194 00004BB2 8903                <1> 	mov	[ebx], eax
  5195                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  5196 00004BB4 E913F0FFFF          <1> 	jmp	sysret
  5197                              <1> 		; br sysret4
  5198                              <1> 
  5199                              <1> systell: ; / get the r/w pointer
  5200                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5201                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5202                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5203                              <1> 	;
  5204                              <1> 	; Retro UNIX 8086 v1 modification:
  5205                              <1> 	; ! 'systell' does not work in original UNIX v1,
  5206                              <1> 	; 	    it returns with error !
  5207                              <1> 	; Inputs: r0 - file descriptor 
  5208                              <1> 	; Outputs: r0 - file r/w pointer
  5209                              <1> 
  5210                              <1> 	;xor	ecx, ecx ; 0
  5211                              <1> 	;mov	edx, 1 ; 05/08/2013
  5212                              <1> 	; 09/01/2022
  5213 00004BB9 29D2                <1> 	sub	edx, edx
  5214 00004BBB FEC2                <1> 	inc	dl
  5215                              <1> 	; edx = 1
  5216                              <1> 	;call 	seektell
  5217 00004BBD E812000000          <1> 	call 	seektell0 ; 05/08/2013
  5218                              <1> 	;mov	ebx, [u.fofp]
  5219 00004BC2 8B03                <1> 	mov	eax, [ebx]
  5220 00004BC4 A3[A46E0000]        <1> 	mov	[u.r0], eax
  5221 00004BC9 E9FEEFFFFF          <1> 	jmp	sysret
  5222                              <1> 
  5223                              <1> ; Original unix v1 'systell' system call:
  5224                              <1> 		; jsr r0,seektell
  5225                              <1> 		; br error4
  5226                              <1> 
  5227                              <1> seektell:
  5228                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  5229                              <1> 	; 06/11/2021
  5230                              <1> 	; 12/06/2021
  5231                              <1> 	; 06/05/2021 (Retro UNIX 386 v2)
  5232                              <1> 	; 03/01/2016
  5233                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5234                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  5235                              <1> 	;
  5236                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  5237                              <1> 	; call in u.base and u.count. It then gets the i-number of
  5238                              <1> 	; the file from the file descriptor in u.r0 and by calling
  5239                              <1> 	; getf. The i-node is brought into core and then u.count
  5240                              <1> 	; is checked to see it is a 0, 1, or 2.
  5241                              <1> 	; If it is 0 - u.count stays the same
  5242                              <1> 	;          1 - u.count = offset (u.fofp)
  5243                              <1> 	;	   2 - u.count = i.size (size of file)
  5244                              <1> 	; 	 		
  5245                              <1> 	; !! Retro UNIX 8086 v1 modification:
  5246                              <1> 	;	Argument 1, file descriptor is in BX;
  5247                              <1> 	;	Argument 2, offset is in CX;
  5248                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  5249                              <1> 	;
  5250                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  5251                              <1> 	; call 	arg
  5252                              <1> 	;
  5253                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  5254                              <1> 	;
  5255 00004BCE 890D[C86E0000]      <1> 	mov 	[u.base], ecx ; offset
  5256                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  5257                              <1> 	; 09/01/2022
  5258                              <1> 	; ebx = file descriptor (0 to 9)
  5259                              <1> seektell0:
  5260 00004BD4 8915[CC6E0000]      <1> 	mov 	[u.count], edx
  5261                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  5262                              <1> 	;mov	ax, bx
  5263                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  5264                              <1> 			     ; / (index in u.fp list)
  5265                              <1> 	; 12/06/2021
  5266                              <1> 	; BX = file descriptor (file number)
  5267 00004BDA E896FCFFFF          <1> 	call	getf
  5268                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  5269                              <1> 	; 09/01/2022
  5270 00004BDF 09C0                <1> 	or	eax, eax
  5271                              <1> 	;or	ax, ax ; i-number of the file
  5272                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  5273                              <1> 		             ; / put it on the stack
  5274                              <1> 	;jz	error
  5275                              <1> 		; beq error4 / if i-number is 0, not active so error
  5276 00004BE1 750F                <1> 	jnz	short seektell1
  5277 00004BE3 C705[186F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  5277 00004BEB 0000                <1>
  5278 00004BED E9BAEFFFFF          <1> 	jmp	error
  5279                              <1> seektell1:
  5280                              <1> 	; 06/05/2021
  5281                              <1> 	;push	eax
  5282                              <1> 	;cmp	ah, 80h
  5283                              <1> 	;jb	short seektell2
  5284                              <1> 	;	; bgt .+4 / if its positive jump
  5285                              <1> 	;neg	ax
  5286                              <1> 	;	; neg r1 / if not make it positive
  5287                              <1> seektell2:
  5288 00004BF2 E879060000          <1> 	call	iget
  5289                              <1> 		; jsr r0,iget / get its i-node into core
  5290                              <1> 	; 09/01/2022
  5291                              <1> 	; (if there is/was an error in 'iget', cpu will not come here)
  5292                              <1> 	;; 06/11/2021
  5293                              <1> 	;jnc	short seektell6
  5294                              <1> 	;mov	[u.error], eax
  5295                              <1> 	;jmp	error
  5296                              <1> seektell6:
  5297 00004BF7 8B1D[B86E0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  5298 00004BFD 803D[CC6E0000]01    <1> 	cmp	byte [u.count], 1
  5299                              <1> 		; cmp u.count,$1 / is ptr name =1
  5300 00004C04 7705                <1> 	ja	short seektell3
  5301                              <1> 		; blt 2f / no its zero
  5302 00004C06 7409                <1> 	je	short seektell4
  5303                              <1> 		; beq 1f / yes its 1
  5304 00004C08 31C0                <1> 	xor	eax, eax
  5305                              <1> 	;jmp	short seektell5
  5306 00004C0A C3                  <1> 	retn
  5307                              <1> seektell3:
  5308                              <1> 	; 03/01/2016
  5309                              <1> 	;;movzx	eax, word [i.size]
  5310                              <1> 	;mov   	ax, [i.size]
  5311                              <1> 	;	; mov i.size,u.count /  put number of bytes 
  5312                              <1> 	;			; / in file in u.count
  5313                              <1> 	;;jmp	short seektell5
  5314                              <1> 	;	; br 2f
  5315                              <1> 	; 06/05/2021 - Retro UNIX 386 v2
  5316 00004C0B A1[486B0000]        <1> 	mov	eax, [i.size]
  5317 00004C10 C3                  <1> 	retn
  5318                              <1> seektell4: ; 1: / ptrname =1
  5319                              <1> 	;mov	ebx, [u.fofp]
  5320 00004C11 8B03                <1> 	mov	eax, [ebx]
  5321                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  5322                              <1> ;seektell5: ; 2: / ptrname =0
  5323                              <1> 	;mov	[u.count], eax
  5324                              <1> 	;pop	eax 
  5325                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  5326 00004C13 C3                  <1> 	retn
  5327                              <1> 		; rts r0
  5328                              <1> 
  5329                              <1> sysintr: ; / set interrupt handling
  5330                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5331                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5332                              <1> 	;
  5333                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  5334                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  5335                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  5336                              <1> 	; If one does the interrupt character in the tty buffer is
  5337                              <1> 	; cleared and 'sysret'is called. If one does not exits
  5338                              <1> 	; 'sysret' is just called.	
  5339                              <1> 	;
  5340                              <1> 	; Calling sequence:
  5341                              <1> 	;	sysintr; arg
  5342                              <1> 	; Argument:
  5343                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  5344                              <1> 	;	    - if 1, intterupts cause their normal result
  5345                              <1> 	;		 i.e force an exit.
  5346                              <1> 	;	    - if arg is a location within the program,
  5347                              <1> 	;		control is passed to that location when
  5348                              <1> 	;		an interrupt occurs.	
  5349                              <1> 	; Inputs: -
  5350                              <1> 	; Outputs: -
  5351                              <1> 	; ...............................................................
  5352                              <1> 	;	
  5353                              <1> 	; Retro UNIX 8086 v1 modification: 
  5354                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  5355                              <1> 	;	then branches into sysquit.
  5356                              <1> 	;
  5357 00004C14 66891D[F06E0000]    <1> 	mov	[u.intr], bx
  5358                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  5359                              <1> 		; br 1f / go into quit routine
  5360 00004C1B E9ACEFFFFF          <1> 	jmp	sysret
  5361                              <1> 
  5362                              <1> sysquit:
  5363                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5364                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5365                              <1> 	;
  5366                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  5367                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  5368                              <1> 	; tty exists. If one does the interrupt character in the tty
  5369                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  5370                              <1> 	; 'sysret' is just called.	
  5371                              <1> 	;
  5372                              <1> 	; Calling sequence:
  5373                              <1> 	;	sysquit; arg
  5374                              <1> 	; Argument:
  5375                              <1> 	;	arg - if 0, this call diables quit signals from the
  5376                              <1> 	;		typewriter (ASCII FS)
  5377                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  5378                              <1> 	;		cease and a core image to be produced.
  5379                              <1> 	;		 i.e force an exit.
  5380                              <1> 	;	    - if arg is an addres in the program,
  5381                              <1> 	;		a quit causes control to sent to that
  5382                              <1> 	;		location.	
  5383                              <1> 	; Inputs: -
  5384                              <1> 	; Outputs: -
  5385                              <1> 	; ...............................................................
  5386                              <1> 	;	
  5387                              <1> 	; Retro UNIX 8086 v1 modification: 
  5388                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  5389                              <1> 	;	then branches into 'sysret'.
  5390                              <1> 	;
  5391 00004C20 66891D[F26E0000]    <1> 	mov	[u.quit], bx
  5392 00004C27 E9A0EFFFFF          <1> 	jmp	sysret
  5393                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  5394                              <1> 	;1:
  5395                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  5396                              <1> 			      ; / to r1
  5397                              <1> 		; beq sysret4 / return to user
  5398                              <1> 		; clrb 6(r1) / clear the interrupt character 
  5399                              <1> 			   ; / in the tty buffer
  5400                              <1> 		; br sysret4 / return to user
  5401                              <1> 
  5402                              <1> syssetuid: ; / set process id
  5403                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5404                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5405                              <1> 	;		(16 bit uid)
  5406                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5407                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  5408                              <1> 	;
  5409                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  5410                              <1> 	; to the process id in (u.r0). Both the effective user u.uid
  5411                              <1> 	; and the real user u.ruid are set to this. 
  5412                              <1> 	; Only the super user can make this call.	
  5413                              <1> 	;
  5414                              <1> 	; Calling sequence:
  5415                              <1> 	;	syssetuid
  5416                              <1> 	; Arguments: -
  5417                              <1> 	;
  5418                              <1> 	; Inputs: (u.r0) - contains the process id.
  5419                              <1> 	; Outputs: -
  5420                              <1> 	; ...............................................................
  5421                              <1> 	;	
  5422                              <1> 	; Retro UNIX 8086 v1 modification: 
  5423                              <1> 	;       BL contains the (new) user ID of the current process
  5424                              <1> 
  5425                              <1> 	; 27/03/2021
  5426                              <1> 	; INPUT:
  5427                              <1> 	;    BX = (new) user ID
  5428                              <1> 
  5429                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  5430                              <1> 	;cmp	bl, [u.ruid] 
  5431                              <1> 	;	; cmpb r1,u.ruid / is it equal to the real user 
  5432                              <1> 			       ; / id number
  5433                              <1> 	; 27/03/2021
  5434 00004C2C 663B1D[F86E0000]    <1> 	cmp	bx, [u.ruid]
  5435 00004C33 7420                <1> 	je	short setuid1
  5436                              <1> 		; beq 1f / yes
  5437                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  5438                              <1> 	;	; tstb u.uid / no, is current user the super user?
  5439                              <1> 	;;ja	error
  5440                              <1> 	;	; bne error4 / no, error
  5441                              <1> 	; 27/03/2021
  5442 00004C35 66833D[F66E0000]00  <1> 	cmp	word [u.uid], 0 
  5443 00004C3D 760F                <1> 	jna	short setuid0
  5444                              <1> setuid_err:
  5445                              <1> setgid_err:
  5446 00004C3F C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  5446 00004C47 0000                <1>
  5447                              <1> 				;  'permission denied !' error
  5448 00004C49 E95EEFFFFF          <1> 	jmp	error
  5449                              <1> setuid0:
  5450                              <1> 	;mov	[u.ruid], bl
  5451                              <1> 	; 27/03/2021
  5452 00004C4E 66891D[F86E0000]    <1> 	mov	[u.ruid], bx
  5453                              <1> setuid1: ; 1:
  5454                              <1> 	;mov	[u.uid], bl ; 02/08/2013
  5455                              <1> 	;	; movb r1,u.uid / put process id in u.uid
  5456                              <1> 	;	; movb r1,u.ruid / put process id in u.ruid
  5457                              <1> 	; 27/03/2021
  5458 00004C55 66891D[F66E0000]    <1> 	mov	[u.uid], bx
  5459 00004C5C E96BEFFFFF          <1> 	jmp	sysret
  5460                              <1> 		; br sysret4 / system return
  5461                              <1> 
  5462                              <1> sysgetuid: ; < get user id >
  5463                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5464                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5465                              <1> 	;		(16 bit uid)
  5466                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5467                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  5468                              <1> 	;
  5469                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  5470                              <1> 	; The real user ID identifies the person who is logged in,
  5471                              <1> 	; in contradistinction to the effective user ID, which
  5472                              <1> 	; determines his access permission at each moment. It is thus
  5473                              <1> 	; useful to programs which operate using the 'set user ID'
  5474                              <1> 	; mode, to find out who invoked them.	
  5475                              <1> 	;
  5476                              <1> 	; Calling sequence:
  5477                              <1> 	;	syssetuid
  5478                              <1> 	; Arguments: -
  5479                              <1> 	;
  5480                              <1> 	; Inputs: -
  5481                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  5482                              <1> 	; ...............................................................
  5483                              <1> 	;	
  5484                              <1> 	; Retro UNIX 8086 v1 modification: 
  5485                              <1> 	;       AL contains the real user ID at return.
  5486                              <1> 	;
  5487                              <1> 	;;movzx eax, byte [u.ruid]
  5488                              <1> 	; 27/03/2021
  5489                              <1> 	;movzx	eax, word [u.ruid]
  5490                              <1> 	; 09/01/2022
  5491 00004C61 66A1[F86E0000]      <1> 	mov	ax, [u.ruid]
  5492 00004C67 A3[A46E0000]        <1> 	mov	[u.r0], eax
  5493                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  5494 00004C6C E95BEFFFFF          <1> 	jmp	sysret
  5495                              <1> 		; br sysret4 / systerm return, sysret
  5496                              <1> 
  5497                              <1> syssetgid: ; set group id
  5498                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5499                              <1> 	; 02/04/2021
  5500                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5501                              <1> 	;
  5502                              <1> 	; 'syssetgid' sets the user's group id (u.gid) 
  5503                              <1> 	;  of the current process to the process id in (u.r0).
  5504                              <1> 	;  Both the effective user u.gid and the real user
  5505                              <1> 	;  u.rgid are set to this. 
  5506                              <1> 	;  Only the super user can make this call.	
  5507                              <1> 	
  5508                              <1> 	; INPUT:
  5509                              <1> 	;	BL = (new) group ID
  5510                              <1> 	; OUTPUT:
  5511                              <1> 	;	-
  5512                              <1> 
  5513 00004C71 3A1D[FB6E0000]      <1> 	cmp	bl, [u.rgid] 
  5514 00004C77 7410                <1> 	je	short setgid1
  5515                              <1> 
  5516                              <1> 	;cmp	byte [u.uid], 0
  5517                              <1> 	; 02/04/2021
  5518 00004C79 66833D[F66E0000]00  <1> 	cmp	word [u.uid], 0
  5519 00004C81 77BC                <1> 	ja	short setgid_err
  5520                              <1> setgid0:
  5521 00004C83 881D[FB6E0000]      <1> 	mov	[u.rgid], bl
  5522                              <1> setgid1: ; 1:
  5523 00004C89 881D[FA6E0000]      <1> 	mov	[u.gid], bl
  5524 00004C8F E938EFFFFF          <1> 	jmp	sysret
  5525                              <1> 
  5526                              <1> sysgetgid: ; < get group id > (& user ID)
  5527                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5528                              <1> 	; 27/03/2021 - Retro UNIX 386 v2
  5529                              <1> 	;
  5530                              <1> 	; 'sysgetgid' returns the real group ID of the current process.
  5531                              <1> 	; The real group ID identifies the group of the person
  5532                              <1> 	; who is logged in, in contradistinction to the effective
  5533                              <1> 	; group ID, which determines his access permission at each moment.
  5534                              <1> 	; It is thus useful to programs which operate using
  5535                              <1> 	; the 'set group ID' mode, to find out the group of the user
  5536                              <1> 	; who invoked them.
  5537                              <1> 
  5538                              <1> 	;movzx	eax, word [u.ruid]
  5539                              <1> 	; 09/01/2022
  5540 00004C94 66A1[F86E0000]      <1> 	mov	ax, [u.ruid]
  5541 00004C9A C1E008              <1> 	shl	eax, 8
  5542                              <1> 	; user ID in byte 1 and byte 2
  5543 00004C9D A0[FB6E0000]        <1> 	mov	al, [u.rgid] ; group ID in byte 0
  5544 00004CA2 A3[A46E0000]        <1> 	mov	[u.r0], eax
  5545 00004CA7 E920EFFFFF          <1> 	jmp	sysret
  5546                              <1> 
  5547                              <1> sysver: ; get operating system version
  5548                              <1> 	; 09/01/2022 - Retro UNIX 386 v1.2
  5549                              <1> 	; 18/06/2021 - Retro UNIX 386 v2
  5550                              <1> 
  5551                              <1> 	;VMAJOR equ 2 ; Retro UNIX 386 v2
  5552                              <1> 	;VMINOR equ 0 ; Retro UNIX 386 v2.0 (v2.0.0)
  5553                              <1> 	;CURRENT_VERSION equ (VMAJOR*256)+VMINOR
  5554                              <1> 
  5555                              <1> 	; 09/01/2022
  5556                              <1> 	VMAJOR equ 1 ; Retro UNIX 386 v1
  5557                              <1> 	VMINOR equ 2 ; Retro UNIX 386 v1.2 (v1.2.0)
  5558                              <1> 	CURRENT_VERSION equ (VMAJOR*256)+VMINOR 		  
  5559                              <1> 
  5560                              <1> 	; 29/04/2016 - TRDOS 386 v2.0
  5561                              <1> 	;mov	dword [u.r0], 200h ; AH = major version, AL = minor version 
  5562                              <1> 	; 18/06/2021
  5563 00004CAC C705[A46E0000]0201- <1> 	mov	dword [u.r0], CURRENT_VERSION ;	(ah = 2, al = 0)
  5563 00004CB4 0000                <1>
  5564 00004CB6 E911EFFFFF          <1> 	jmp	sysret
  5565                              <1> 
  5566                              <1> anyi: 
  5567                              <1> 	; 09/01/2022
  5568                              <1> 	; 02/01/2022
  5569                              <1> 	; 01/01/2022
  5570                              <1> 	; 27/12/2021 (Retro UNIX 386 v1.2)
  5571                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  5572                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  5573                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  5574                              <1> 	;
  5575                              <1> 	; 'anyi' is called if a file deleted while open.
  5576                              <1> 	; "anyi" checks to see if someone else has opened this file.
  5577                              <1> 	;
  5578                              <1> 	; INPUTS ->
  5579                              <1> 	;    r1 - contains an i-number
  5580                              <1> 	;    fsp - start of table containing open files
  5581                              <1> 	;
  5582                              <1> 	; OUTPUTS ->
  5583                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  5584                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  5585                              <1> 	;    if file not found - bit in i-node map is cleared
  5586                              <1> 	;    			 (i-node is freed)
  5587                              <1> 	;               all blocks related to i-node are freed
  5588                              <1> 	;	        all flags in i-node are cleared
  5589                              <1> 	; ((AX = R1)) input
  5590                              <1> 	;
  5591                              <1> 	;    (Retro UNIX Prototype: 02/12/2012, UNIXCOPY.ASM)
  5592                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  5593                              <1> 	;
  5594                              <1> 		; / r1 contains an i-number
  5595 00004CBB BB[406B0000]        <1> 	mov	ebx, fsp
  5596                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  5597                              <1> anyi_1: ; 1:
  5598                              <1> 	;cmp	eax, [ebx] ; 09/01/2022 (32 bit inode number)
  5599 00004CC0 663B03              <1> 	cmp	ax, [ebx]
  5600                              <1> 		; cmp r1,(r2) / do i-numbers match?
  5601 00004CC3 7423                <1> 	je	short anyi_3
  5602                              <1> 		; beq 1f / yes, 1f
  5603                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5604                              <1> 	;neg	ax
  5605                              <1> 	;	; neg r1 / no complement r1
  5606                              <1> 	;cmp	ax, [ebx]
  5607                              <1> 	;	; cmp r1,(r2) / do they match now?
  5608                              <1> 	;je	short anyi_3
  5609                              <1> 		; beq 1f / yes, transfer
  5610                              <1> 		; / i-numbers do not match
  5611                              <1> anyi_0:
  5612                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5613                              <1> 	;add	ebx, fp.size ; runix v2 fsp table size is 16 bytes
  5614                              <1> 	; 01/01/2022
  5615 00004CC5 83C310              <1> 	add	ebx, 16 ; runix v2 fsp table size is 16 bytes
  5616                              <1> 	;;add	ebx, 10 ; fsp table size is 10 bytes
  5617                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  5618                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  5619                              <1> 	; 22/11/2021
  5620                              <1> 	;cmp	ebx, fsp + (NFILES*fp.size) ; fsp+(NFILES*16)
  5621                              <1> 	; 02/01/2022
  5622 00004CC8 81FB[606E0000]      <1> 	cmp	ebx, fsp + (nfiles*16)
  5623                              <1> 	; 01/01/2022
  5624                              <1> 	;cmp	ebx, fsp + (NFILES*16) ; fsp+(NFILES*fp.size)
  5625                              <1> 	;;cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  5626                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  5627                              <1> 			; / are we at last entry in the table
  5628 00004CCE 72F0                <1> 	jb	short anyi_1
  5629                              <1> 		; blt 1b / no, check next entries i-number
  5630                              <1> 	; 27/12/2021
  5631                              <1> 	;;cmp	ax, 32768
  5632                              <1> 	;cmp	ah, 80h ; negative number check
  5633                              <1> 	;	; tst r1 / yes, no match
  5634                              <1> 	;	; bge .+4
  5635                              <1> 	;jb	short anyi_2
  5636                              <1> 	;neg	ax
  5637                              <1> 	;	; neg r1 / make i-number positive
  5638                              <1> ;anyi_2:	
  5639 00004CD0 E85B080000          <1> 	call	imap
  5640                              <1> 		; jsr r0,imap / get address of allocation bit 
  5641                              <1> 			    ; / in the i-map in r2
  5642                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  5643                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  5644                              <1>  	; not	dx
  5645 00004CD5 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  5646                              <1>         ;and	[ebx], dx
  5647 00004CD7 2013                <1> 	and 	[ebx], dl 
  5648                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  5649 00004CD9 E853070000          <1> 	call	itrunc
  5650                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  5651 00004CDE 66C705[406B0000]00- <1>  	mov 	word [i.flgs], 0
  5651 00004CE6 00                  <1>
  5652                              <1> 		; clr i.flgs / clear all flags in the i-node
  5653 00004CE7 C3                  <1> 	retn
  5654                              <1> 		;rts	r0 / return
  5655                              <1> anyi_3: ; 1: / i-numbers match
  5656                              <1> 	; 09/01/2022
  5657 00004CE8 F6430501            <1> 	test	byte [ebx+5], 1 ; open for writing flag
  5658 00004CEC 74D7                <1> 	jz	short anyi_0	
  5659                              <1> 
  5660                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5661 00004CEE 804B0580            <1> 	or	byte [ebx+5], 80h ; set deleted file flag (bit 7)
  5662                              <1> 	; 22/06/2015
  5663                              <1> 	;inc 	byte [ebx+9]
  5664                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  5665                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  5666 00004CF2 C3                  <1> 	retn
  5667                              <1> 		; rts r0
  2078                                  %include 'u3.s'      ; 10/05/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) - SYS3.INC
  2083                              <1> ; Last Modification: 24/12/2021
  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 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2094                              <1> ;
  2095                              <1> ; ****************************************************************************
  2096                              <1> 
  2097                              <1> tswitch: ; Retro UNIX 386 v1
  2098                              <1> tswap:
  2099                              <1> 	; 01/09/2015
  2100                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2101                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2102                              <1> 	; time out swap, called when a user times out.
  2103                              <1> 	; the user is put on the low priority queue.
  2104                              <1> 	; This is done by making a link from the last user
  2105                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2106                              <1> 	; then he is swapped out.
  2107                              <1> 	;
  2108                              <1> 	; Retro UNIX 386 v1 modification ->
  2109                              <1> 	;       swap (software task switch) is performed by changing
  2110                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2111                              <1> 	;	as in Retro UNIX 8086 v1.
  2112                              <1> 	;
  2113                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2114                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2115                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2116                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2117                              <1> 	;	compatibles was using 1MB segmented memory 
  2118                              <1> 	;	in 8086/8088 times.
  2119                              <1> 	;
  2120                              <1> 	; INPUTS ->
  2121                              <1> 	;    u.uno - users process number
  2122                              <1> 	;    runq+4 - lowest priority queue
  2123                              <1> 	; OUTPUTS ->
  2124                              <1> 	;    r0 - users process number
  2125                              <1> 	;    r2 - lowest priority queue address
  2126                              <1> 	;
  2127                              <1> 	; ((AX = R0, BX = R2)) output
  2128                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2129                              <1> 	;
  2130 00004CF3 A0[F56E0000]        <1> 	mov 	al, [u.uno]
  2131                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2132                              <1> 		; mov  $runq+4,r2 
  2133                              <1> 			; / move lowest priority queue address to r2
  2134 00004CF8 E8CD000000          <1>         call 	putlu
  2135                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2136                              <1> 		             ; / u.uno's user
  2137                              <1> 
  2138                              <1> switch: ; Retro UNIX 386 v1
  2139                              <1> swap:
  2140                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2141                              <1> 	; 02/09/2015
  2142                              <1> 	; 01/09/2015
  2143                              <1> 	; 31/08/2015
  2144                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2145                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2146                              <1> 	; 'swap' is routine that controls the swapping of processes
  2147                              <1> 	; in and out of core.
  2148                              <1> 	;
  2149                              <1> 	; Retro UNIX 386 v1 modification ->
  2150                              <1> 	;       swap (software task switch) is performed by changing
  2151                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2152                              <1> 	;	as in Retro UNIX 8086 v1.
  2153                              <1> 	;
  2154                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2155                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2156                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2157                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2158                              <1> 	;	compatibles was using 1MB segmented memory 
  2159                              <1> 	;	in 8086/8088 times.
  2160                              <1> 	;
  2161                              <1> 	; INPUTS ->
  2162                              <1> 	;    runq table - contains processes to run.
  2163                              <1> 	;    p.link - contains next process in line to be run.
  2164                              <1> 	;    u.uno - process number of process in core	
  2165                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2166                              <1> 	; OUTPUTS ->
  2167                              <1> 	;    (original unix v1 -> present process to its disk block)
  2168                              <1> 	;    (original unix v1 -> new process into core -> 
  2169                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2170                              <1> 	;	   for new process)
  2171                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2172                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2173                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2174                              <1> 	;	 for now, it will swap the process if there is not
  2175                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2176                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2177                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2178                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2179                              <1> 	;
  2180                              <1> 	;    u.pri -points to highest priority run Q.
  2181                              <1> 	;    r2 - points to the run queue.
  2182                              <1> 	;    r1 - contains new process number
  2183                              <1> 	;    r0 - points to place in routine or process that called
  2184                              <1> 	;	  swap all user parameters
  2185                              <1> 	;				
  2186                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2187                              <1> 	;
  2188                              <1> swap_0:
  2189                              <1> 		;mov $300,*$ps / processor priority = 6
  2190 00004CFD BE[946E0000]        <1> 	mov	esi, runq
  2191                              <1> 		; mov $runq,r2 / r2 points to runq table
  2192                              <1> swap_1: ; 1: / search runq table for highest priority process
  2193 00004D02 668B06              <1> 	mov	ax, [esi]
  2194 00004D05 6621C0              <1> 	and 	ax, ax
  2195                              <1>        		; tst (r2)+ / are there any processes to run 
  2196                              <1> 			  ; / in this Q entry
  2197 00004D08 7507                <1> 	jnz	short swap_2
  2198                              <1>        		; bne 1f / yes, process 1f
  2199                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2200                              <1> 			       ; / to end of table
  2201                              <1> 		; bne 1b / if not at end, go back
  2202 00004D0A E8E0000000          <1> 	call	idle
  2203                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2204                              <1> 				       ; / all queues are empty
  2205 00004D0F EBF1                <1> 	jmp	short swap_1
  2206                              <1> 		; br swap
  2207                              <1> swap_2: ; 1:
  2208 00004D11 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2209                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2210                              <1>  		; mov r2,u.pri / set present user to this run queue
  2211                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2212 00004D14 38E0                <1> 	cmp	al, ah
  2213                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2214                              <1> 			      ; / in this Q to be run
  2215 00004D16 740A                <1> 	je	short swap_3
  2216                              <1>        		; beq 1f / yes
  2217                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2218                              <1> 	;movzx	ebx, al
  2219 00004D18 8AA3[FF6B0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2220 00004D1E 8826                <1>        	mov	[esi], ah
  2221                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2222                              <1> 				       ; / in line into run queue
  2223 00004D20 EB05                <1> 	jmp	short swap_4
  2224                              <1>        		; br 2f
  2225                              <1> swap_3: ; 1:
  2226                              <1> 	;xor	dx, dx
  2227                              <1> 	; 24/12/2021
  2228 00004D22 31D2                <1> 	xor	edx, edx
  2229 00004D24 668916              <1> 	mov	[esi], dx
  2230                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2231                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2232                              <1>       ; / in new process if required
  2233                              <1>        		; clr *$ps / clear processor status
  2234 00004D27 8A25[F56E0000]      <1> 	mov 	ah, [u.uno]
  2235 00004D2D 38C4                <1> 	cmp	ah, al
  2236                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2237                              <1> 			      ; / the process in core?
  2238 00004D2F 743B                <1>        	je	short swap_8
  2239                              <1>        		; beq 2f / yes, don't have to swap
  2240                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2241                              <1> 			   ; / (address in routine that called swap)
  2242                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2243                              <1> 	; 01/09/2015
  2244                              <1> 	;mov	[u.usp], esp
  2245                              <1>        		; mov sp,u.usp / save stack pointer
  2246                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2247                              <1> 			       ; / to the stack pointer
  2248 00004D31 08E4                <1> 	or	ah, ah
  2249                              <1>        		; tstb u.uno / is the process # = 0
  2250 00004D33 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2251                              <1> 		; beq  1f / yes, kill process by overwriting
  2252                              <1> 	; 02/09/2015
  2253 00004D35 8925[A06E0000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2254                              <1> 	;
  2255 00004D3B E834000000          <1> 	call	wswap
  2256                              <1> 		;jsr r0,wswap / write out core to disk
  2257                              <1> 	 ; 31/08/2015
  2258                              <1> 	;movzx	ebx, al ; New (running) process number
  2259 00004D40 EB1C                <1> 	jmp 	short swap_7
  2260                              <1> swap_6:
  2261                              <1> 	; 31/08/2015
  2262                              <1> 	; Deallocate memory pages belong to the process
  2263                              <1> 	; which is being terminated
  2264                              <1> 	; 14/05/2015 ('sysexit')
  2265                              <1>  	; Deallocate memory pages of the process
  2266                              <1> 	; (Retro UNIX 386 v1 modification !)
  2267                              <1> 	;
  2268                              <1> 	; movzx ebx, al
  2269 00004D42 53                  <1> 	push	ebx
  2270 00004D43 A1[046F0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2271 00004D48 8B1D[086F0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2272 00004D4E E845E2FFFF          <1> 	call	deallocate_page_dir
  2273 00004D53 A1[006F0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2274 00004D58 E8D3E2FFFF          <1> 	call	deallocate_page
  2275 00004D5D 5B                  <1> 	pop	ebx
  2276                              <1> swap_7: ;1: 
  2277                              <1> 	; 02/09/2015
  2278                              <1> 	; 31/08/2015
  2279                              <1> 	; 14/05/2015
  2280 00004D5E C0E302              <1> 	shl	bl, 2 ; * 4 
  2281 00004D61 8B83[1C6C0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2282                              <1> 	;cli
  2283 00004D67 E831000000          <1> 	call	rswap
  2284                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2285                              <1> 		; jsr r0,rswap / read new process into core
  2286                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2287                              <1> 			      ; / to his program to its normal
  2288                              <1> 	; 01/09/2015
  2289                              <1> 	;mov	esp, [u.usp]	
  2290                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2291                              <1> 			     ; / new process stack
  2292                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2293                              <1> 			     ; / that just got swapped in, left off.,
  2294                              <1> 			     ; / i.e., transfer control to new process
  2295                              <1> 	;sti
  2296                              <1> swap_8: ;2:
  2297                              <1> 	; RETRO UNIX 8086 v1 modification !
  2298 00004D6C C605[EC6E0000]04    <1> 	mov	byte [u.quant], time_count 
  2299                              <1> 		; movb $30.,uquant / initialize process time quantum
  2300 00004D73 C3                  <1> 	retn
  2301                              <1> 		; rts r0 / return
  2302                              <1> 
  2303                              <1> wswap:  ; < swap out, swap to disk >
  2304                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2305                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2306                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2307                              <1> 	; appropriate disk area.
  2308                              <1> 	;
  2309                              <1> 	; Retro UNIX 386 v1 modification ->
  2310                              <1> 	;       User (u) structure content and the user's register content
  2311                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2312                              <1> 	;	saving 'u' structure and user registers for task switching).
  2313                              <1> 	;	u.usp - points to kernel stack address which contains
  2314                              <1> 	;		user's registers while entering system call.  
  2315                              <1> 	;	u.sp  - points to kernel stack address 
  2316                              <1> 	;		to return from system call -for IRET-.
  2317                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2318                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2319                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2320                              <1> 	;
  2321                              <1> 	; Retro UNIX 8086 v1 modification ->
  2322                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2323                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2324                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2325                              <1> 	;	compatibles was using 1MB segmented memory 
  2326                              <1> 	;	in 8086/8088 times.
  2327                              <1> 	;
  2328                              <1> 	; INPUTS ->
  2329                              <1> 	;    u.break - points to end of program
  2330                              <1> 	;    u.usp - stack pointer at the moment of swap
  2331                              <1> 	;    core - beginning of process program		
  2332                              <1> 	;    ecore - end of core 	
  2333                              <1> 	;    user - start of user parameter area		
  2334                              <1> 	;    u.uno - user process number	
  2335                              <1> 	;    p.dska - holds block number of process	
  2336                              <1> 	; OUTPUTS ->
  2337                              <1> 	;    swp I/O queue
  2338                              <1> 	;    p.break - negative word count of process 
  2339                              <1> 	;    r1 - process disk address	
  2340                              <1> 	;    r2 - negative word count
  2341                              <1> 	;
  2342                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2343                              <1> 	;
  2344                              <1> 	; INPUTS ->
  2345                              <1> 	;    u.uno - process number (to be swapped out)
  2346                              <1> 	; OUTPUTS ->
  2347                              <1> 	;    none
  2348                              <1> 	;
  2349                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2350                              <1> 	;
  2351 00004D74 8B3D[006F0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2352 00004D7A B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2353 00004D7F BE[9C6E0000]        <1> 	mov	esi, user ; active user (u) structure	
  2354 00004D84 F3A5                <1> 	rep	movsd
  2355                              <1> 	;
  2356 00004D86 8B35[A06E0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2357                              <1> 			     ;      points to user registers)
  2358 00004D8C 8B0D[9C6E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2359                              <1> 			     ; (for IRET)
  2360                              <1> 			     ; [u.sp] -> EIP (user)
  2361                              <1> 			     ; [u.sp+4]-> CS (user)
  2362                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2363                              <1> 			     ; [u.sp+12] -> ESP (user)
  2364                              <1> 			     ; [u.sp+16] -> SS (user)	
  2365 00004D92 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2366 00004D94 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2367                              <1> 			     ; (for IRET) 	
  2368 00004D97 C1E902              <1> 	shr	ecx, 2	     		
  2369 00004D9A F3A5                <1> 	rep	movsd
  2370 00004D9C C3                  <1> 	retn
  2371                              <1> 
  2372                              <1> 	; Original UNIX v1 'wswap' routine:
  2373                              <1> 	; wswap:
  2374                              <1> 		; mov *$30,u.emt / determines handling of emts
  2375                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2376                              <1> 				; / illegal instructions
  2377                              <1> 		; mov u.break,r2 / put process program break address in r2
  2378                              <1> 		; inc r2 / add 1 to it 
  2379                              <1> 		; bic $1,r2 / make it even
  2380                              <1> 		; mov r2,u.break / set break to an even location
  2381                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2382                              <1> 			     ; / at moment of swap in r3
  2383                              <1> 		; cmp r2,$core / is u.break less than $core
  2384                              <1> 		; blos 2f / yes
  2385                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2386                              <1>        		; bhis 2f / yes
  2387                              <1> 	; 1:
  2388                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2389                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2390                              <1> 		; bne 1b / no, keep packing
  2391                              <1> 	 	; br 1f / yes
  2392                              <1> 	; 2:
  2393                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2394                              <1> 	; 1:
  2395                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2396                              <1> 			   ; / (user up to end of stack gets written out)
  2397                              <1> 		; neg r2 / make it negative
  2398                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2399                              <1> 		; mov r2,swp+4 / word count
  2400                              <1> 		; movb u.uno,r1 / move user process number to r1
  2401                              <1> 		; asl r1 / x2 for index
  2402                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2403                              <1> 				     ; / into the p.break table
  2404                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2405                              <1> 				    ; /	for process to r1
  2406                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2407                              <1> 			     ; / (block number)
  2408                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2409                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2410                              <1> 	; 1:
  2411                              <1>        		; tstb swp+1 / is lt done writing?
  2412                              <1>        		; bne 1b / no, wait
  2413                              <1> 		; rts r0 / yes, return to swap
  2414                              <1> 
  2415                              <1> rswap:  ; < swap in, swap from disk >
  2416                              <1> 	; 15/09/2015
  2417                              <1> 	; 28/08/2015
  2418                              <1> 	; 14/05/2015
  2419                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2420                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2421                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2422                              <1> 	; from disk into core.
  2423                              <1> 	;
  2424                              <1> 	; Retro UNIX 386 v1 modification ->
  2425                              <1> 	;       User (u) structure content and the user's register content
  2426                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2427                              <1> 	;	saving 'u' structure and user registers for task switching).
  2428                              <1> 	;	u.usp - points to kernel stack address which contains
  2429                              <1> 	;		user's registers while entering system call.  
  2430                              <1> 	;	u.sp  - points to kernel stack address 
  2431                              <1> 	;		to return from system call -for IRET-.
  2432                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2433                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2434                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2435                              <1> 	;
  2436                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2437                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2438                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2439                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2440                              <1> 	;	compatibles was using 1MB segmented memory 
  2441                              <1> 	;	in 8086/8088 times.
  2442                              <1> 	;
  2443                              <1> 	; INPUTS ->
  2444                              <1> 	;    r1 - process number of process to be read in
  2445                              <1> 	;    p.break - negative of word count of process 
  2446                              <1> 	;    p.dska - disk address of the process		
  2447                              <1> 	;    u.emt - determines handling of emt's 	
  2448                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2449                              <1> 	; OUTPUTS ->
  2450                              <1> 	;    8 = (u.ilgins)
  2451                              <1> 	;    24 = (u.emt)
  2452                              <1> 	;    swp - bit 10 is set to indicate read 
  2453                              <1> 	;		(bit 15=0 when reading is done)	
  2454                              <1> 	;    swp+2 - disk block address
  2455                              <1> 	;    swp+4 - negative word count 	
  2456                              <1> 	;      ((swp+6 - address of user structure)) 
  2457                              <1> 	;
  2458                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2459                              <1> 	;
  2460                              <1> 	; INPUTS ->
  2461                              <1> 	;    AL	- new process number (to be swapped in)	 
  2462                              <1> 	; OUTPUTS ->
  2463                              <1> 	;    none
  2464                              <1> 	;
  2465                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2466                              <1> 	;
  2467                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2468 00004D9D 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2469 00004D9F B921000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2470 00004DA4 BF[9C6E0000]        <1> 	mov	edi, user ; active user (u) structure	
  2471 00004DA9 F3A5                <1> 	rep	movsd
  2472 00004DAB 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2473 00004DAC 8B3D[A06E0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2474                              <1> 			     ;      points to user registers)
  2475 00004DB2 8B0D[9C6E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2476                              <1> 			     ; (for IRET)
  2477                              <1> 			     ; [u.sp] -> EIP (user)
  2478                              <1> 			     ; [u.sp+4]-> CS (user)
  2479                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2480                              <1> 			     ; [u.sp+12] -> ESP (user)
  2481                              <1> 			     ; [u.sp+16] -> SS (user)		
  2482                              <1> 	; 28/08/2015
  2483 00004DB8 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2484 00004DBA 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2485                              <1> 			     ; (for IRET) 	
  2486 00004DBD C1E902              <1> 	shr	ecx, 2	       		
  2487 00004DC0 F3A5                <1> 	rep	movsd
  2488 00004DC2 8B25[A06E0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2489 00004DC8 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2490 00004DC9 C3                  <1> 	retn
  2491                              <1> 
  2492                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2493                              <1> 	;rswap:
  2494                              <1>        		; asl r1 / process number x2 for index
  2495                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2496                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2497                              <1>        		; bis $2000,swp / read
  2498                              <1>        		; jsr r0,ppoke / read it in 
  2499                              <1> 	; 1:
  2500                              <1>        		; tstb swp+1 / done
  2501                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2502                              <1>        		; mov u.emt,*$30 / yes move these
  2503                              <1>        		; mov u.ilgins,*$10 / back
  2504                              <1>        		; rts r0 / return
  2505                              <1> 
  2506                              <1> 	;unpack: ; / move stack back to its normal place
  2507                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2508                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2509                              <1> 		; blos 2f / yes, return
  2510                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2511                              <1> 			     ; / before swapping
  2512                              <1> 		; bhis 2f / yes, return
  2513                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2514                              <1> 		; add r3,r2
  2515                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2516                              <1> 	; 1:
  2517                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2518                              <1> 		; cmp r2,u.break / in core
  2519                              <1> 		; bne 1b
  2520                              <1> 	; 2:
  2521                              <1>        		; rts r0
  2522                              <1> 
  2523                              <1> putlu: 
  2524                              <1> 	; 12/09/2015
  2525                              <1> 	; 02/09/2015
  2526                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2527                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2528                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2529                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2530                              <1> 	; the last process on the queue to process in r1 by putting
  2531                              <1> 	; the process number in r1 into the last process's link.
  2532                              <1> 	;
  2533                              <1> 	; INPUTS ->
  2534                              <1> 	;    r1 - user process number
  2535                              <1> 	;    r2 - points to lowest priority queue 
  2536                              <1> 	;    p.dska - disk address of the process		
  2537                              <1> 	;    u.emt - determines handling of emt's 	
  2538                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2539                              <1> 	; OUTPUTS ->
  2540                              <1> 	;    r3 - process number of last process on the queue upon
  2541                              <1> 	;	  entering putlu
  2542                              <1> 	;    p.link-1 + r3 - process number in r1
  2543                              <1> 	;    r2 - points to lowest priority queue
  2544                              <1> 	;
  2545                              <1> 	; ((Modified registers: EDX, EBX)) 
  2546                              <1> 	;
  2547                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2548                              <1> 
  2549                              <1> 	; eBX = r2
  2550                              <1> 	; eAX = r1 (AL=r1b)
  2551                              <1> 
  2552 00004DCA BB[946E0000]        <1> 	mov	ebx, runq
  2553 00004DCF 0FB613              <1> 	movzx  	edx, byte [ebx]
  2554 00004DD2 43                  <1> 	inc	ebx
  2555 00004DD3 20D2                <1> 	and	dl, dl
  2556                              <1> 		; tstb (r2)+ / is queue empty?
  2557 00004DD5 740A                <1>        	jz	short putlu_1
  2558                              <1> 		; beq 1f / yes, branch
  2559 00004DD7 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2560                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2561                              <1> 			     ; / in r3
  2562 00004DD9 8882[FF6B0000]      <1>        	mov	[edx+p.link-1], al
  2563                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2564                              <1> 			     ; / "last users" link
  2565 00004DDF EB03                <1> 	jmp	short putlu_2
  2566                              <1> 		; br 2f /
  2567                              <1> putlu_1: ; 1:
  2568 00004DE1 8843FF              <1> 	mov	[ebx-1], al
  2569                              <1>        		; movb r1,-1(r2) / user is only user; 
  2570                              <1> 			    ; / put process no. at beginning and at end
  2571                              <1> putlu_2: ; 2: 
  2572 00004DE4 8803                <1> 	mov	[ebx], al
  2573                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2574                              <1> 			     ; / on the queue
  2575 00004DE6 88C2                <1> 	mov	dl, al
  2576 00004DE8 88B2[FF6B0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2577                              <1> 		; dec r2 / restore r2
  2578 00004DEE C3                  <1>         retn
  2579                              <1> 		; rts r0
  2580                              <1> 
  2581                              <1> ;copyz:
  2582                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2583                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2584                              <1> ;       mov     (r0)+,r1
  2585                              <1> ;       mov     (r0)+,r2
  2586                              <1> ;1:
  2587                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2588                              <1> ;       cmp     r1,r2 
  2589                              <1> ;       blo     1b
  2590                              <1> ;       mov     (sp)+,r2 / restore r2
  2591                              <1> ;       mov     (sp)+,r1 / restore r1
  2592                              <1> ;       rts     r0 
  2593                              <1> 
  2594                              <1> idle:
  2595                              <1> 	; 01/09/2015
  2596                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2597                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2598                              <1> 	; (idle & wait loop)
  2599                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2600                              <1> 	; idle procedure!
  2601                              <1>       	;
  2602                              <1>   	; 01/09/2015
  2603 00004DEF FB                  <1> 	sti
  2604                              <1>       	; 29/07/2013
  2605 00004DF0 F4                  <1>       	hlt
  2606 00004DF1 90                  <1>       	nop ; 10/10/2013
  2607 00004DF2 90                  <1>       	nop
  2608 00004DF3 90                  <1>       	nop
  2609                              <1>       	; 23/10/2013
  2610 00004DF4 90                  <1>       	nop
  2611 00004DF5 90                  <1>       	nop
  2612 00004DF6 90                  <1>       	nop
  2613 00004DF7 90                  <1>       	nop
  2614 00004DF8 C3                  <1>       	retn      
  2615                              <1> 
  2616                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2617                              <1> 	;clr *$ps / clear ps
  2618                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2619                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2620                              <1> 	;1 / wait for interrupt
  2621                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2622                              <1> 	;mov (sp)+,*$ps
  2623                              <1> 	;rts r0
  2624                              <1> 
  2625                              <1> clear:
  2626                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2627                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2628                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2629                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2630                              <1> 	; on the current device (cdev)
  2631                              <1> 	;	
  2632                              <1> 	; INPUTS ->
  2633                              <1> 	;    r1 - block number of block to be zeroed
  2634                              <1> 	;    cdev - current device number 
  2635                              <1> 	; OUTPUTS ->
  2636                              <1> 	;    a zeroed I/O buffer onto the current device
  2637                              <1> 	;    r1 - points to last entry in the I/O buffer
  2638                              <1> 	;
  2639                              <1> 	; ((AX = R1)) input/output
  2640                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2641                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2642                              <1> 
  2643 00004DF9 E883110000          <1> 	call 	wslot
  2644                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2645                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2646 00004DFE 89DF                <1> 	mov	edi, ebx ; r5
  2647 00004E00 89C2                <1> 	mov	edx, eax
  2648 00004E02 B980000000          <1> 	mov	ecx, 128
  2649                              <1> 		; mov $256.,r3
  2650 00004E07 31C0                <1> 	xor	eax, eax
  2651 00004E09 F3AB                <1> 	rep	stosd
  2652 00004E0B 89D0                <1> 	mov	eax, edx
  2653                              <1> ; 1: 
  2654                              <1>        		; clr (r5)+ / zero data word in buffer
  2655                              <1>        		; dec r3
  2656                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2657                              <1> 	;call	dskwr
  2658                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2659                              <1>                              ; / block specified in r1
  2660                              <1> 	; eAX (r1) = block number
  2661                              <1> 	;retn
  2662                              <1> 		; rts r0
  2663                              <1> 	; 24/12/2021
  2664 00004E0D E98B110000          <1> 	jmp	dskwr
  2079                                  %include 'u4.s'      ; 15/04/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) - SYS4.INC
  2084                              <1> ; Last Modification: 05/12/2021
  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 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2095                              <1> ;
  2096                              <1> ; ****************************************************************************
  2097                              <1> 
  2098                              <1> ;setisp:
  2099                              <1>        ;mov     r1,-(sp)
  2100                              <1>        ;mov     r2,-(sp)
  2101                              <1>        ;mov     r3,-(sp)
  2102                              <1>        ;mov     clockp,-(sp)
  2103                              <1>        ;mov     $s.syst+2,clockp
  2104                              <1>        ;jmp     (r0)
  2105                              <1> 
  2106                              <1> clock: ; / interrupt from 60 cycle clock
  2107                              <1> 	
  2108                              <1> 	; 14/10/2015
  2109                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2110                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2111                              <1> 
  2112                              <1>        ;mov     r0,-(sp) / save r0
  2113                              <1>        ;tst     *$lks / restart clock?
  2114                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2115                              <1>        ;inc     (r0)
  2116                              <1>        ;bne     1f
  2117                              <1>        ;inc     -(r0)
  2118                              <1> ;1:
  2119                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2120                              <1>        ;inc     (r0)
  2121                              <1>        ;bne     1f
  2122                              <1>        ;inc     -(r0)
  2123                              <1> ;1:
  2124                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2125                              <1> 
  2126 00004E12 803D[EC6E0000]00    <1> 	cmp	byte [u.quant], 0
  2127 00004E19 772C                <1> 	ja	short clk_1
  2128                              <1> 	;
  2129 00004E1B 803D[9A6E0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2130 00004E22 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2131 00004E24 803D[F56E0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2132 00004E2B 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2133 00004E2D 66833D[F06E0000]00  <1> 	cmp	word [u.intr], 0
  2134 00004E35 7616                <1> 	jna	short clk_2
  2135                              <1> clk_0:
  2136                              <1> 	; 14/10/2015
  2137 00004E37 FE05[9A6E0000]      <1> 	inc	byte [sysflg] ; Now, we are in system space
  2138 00004E3D 58                  <1> 	pop	eax ; return address to the timer interrupt
  2139                              <1> 	;
  2140 00004E3E B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2141                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2142 00004E40 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2143                              <1> 	;
  2144 00004E42 E9EAEDFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2145                              <1> clk_1:
  2146 00004E47 FE0D[EC6E0000]      <1> 	dec	byte [u.quant]
  2147                              <1> clk_2:
  2148 00004E4D C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2149                              <1> 
  2150                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2151                              <1> 
  2152                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2153                              <1>        ;decb    (r0)
  2154                              <1>        ;bge     1f / if less than 0
  2155                              <1>        ;clrb    (r0) / make it 0
  2156                              <1> ;1: / decrement time out counts return now if priority was not 0
  2157                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2158                              <1>        ;bge     2f / yes, check time outs
  2159                              <1>        ;tstb    (r0) / no, user timed out?
  2160                              <1>        ;bne     1f / no
  2161                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2162                              <1>        ;bne     1f / no, 1f
  2163                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2164                              <1>        ;sys     0 / sysrele
  2165                              <1>        ;rti
  2166                              <1> ;2: / priority is high so just decrement time out counts
  2167                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2168                              <1> ;2:
  2169                              <1>        ;tstb    (r0) / is the time out?
  2170                              <1>        ;beq     3f / yes, 3f (get next entry)
  2171                              <1>        ;decb    (r0) / no, decrement the time
  2172                              <1>        ;bne     3f / isit zero now?
  2173                              <1>        ;incb    (r0) / yes, increment the time
  2174                              <1> ;3:
  2175                              <1>        ;inc     r0 / next entry
  2176                              <1>        ;cmp     r0,$touts / end of toutt table?
  2177                              <1>        ;blo     2b / no, check this entry
  2178                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2179                              <1>        ;rti / return from interrupt
  2180                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2181                              <1>        ;mov     (sp)+,r0 / restore r0
  2182                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2183                              <1>        ;jsr     r0,setisp / save registers
  2184                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2185                              <1>                                ;  / the table
  2186                              <1> ;1:
  2187                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2188                              <1>        ;beq     2f / yes
  2189                              <1>        ;decb    toutt(r0) / no, decrement the time
  2190                              <1>        ;bne     2f / is the time 0, now
  2191                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2192                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2193                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2194                              <1> ;2:
  2195                              <1>        ;dec     r0 / set up r0 for next entry
  2196                              <1>        ;bge     1b / finished? , no, go back
  2197                              <1>        ;br      retisp / yes, restore registers and do a rti
  2198                              <1> 
  2199                              <1> ;retisp:
  2200                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2201                              <1>        ;mov     (sp)+,r3
  2202                              <1>        ;mov     (sp)+,r2
  2203                              <1>        ;mov     (sp)+,r1
  2204                              <1>        ;mov     (sp)+,r0
  2205                              <1>        ;rti     / return from interrupt
  2206                              <1> 
  2207                              <1> 
  2208                              <1> wakeup: ; / wakeup processes waiting for an event 
  2209                              <1> 	; / by linking them to the queue
  2210                              <1> 	;
  2211                              <1> 	; 15/09/2015
  2212                              <1> 	; 29/06/2015
  2213                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2214                              <1> 	;
  2215                              <1> 	; 15/05/2013 - 02/06/2014
  2216                              <1> 	; Retro UNIX 8086 v1 modification !
  2217                              <1> 	; (Process/task switching routine by using
  2218                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2219                              <1> 	;
  2220                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2221                              <1> 	; sleeping in the specified wait channel by creating a link 
  2222                              <1> 	; to it from the last user process on the run queue.
  2223                              <1> 	; If there is no process to wake up, nothing happens.
  2224                              <1> 	;
  2225                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2226                              <1> 	; 'switching' status of the current process (owns current tty)
  2227                              <1> 	; (via alt + function keys) to a process which has highest
  2228                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2229                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2230                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2231                              <1> 	; tty for tty switching by keyboard.)	 
  2232                              <1> 	; 
  2233                              <1> 	; INPUT -> 
  2234                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2235                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2236                              <1> 	;
  2237                              <1> 	; ((modified registers: EAX, EBX))
  2238                              <1> 	;
  2239 00004E4E 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2240 00004E51 81C3[086E0000]      <1> 	add	ebx, wlist
  2241 00004E57 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2242 00004E59 20C0                <1> 	and	al, al
  2243 00004E5B 7424                <1> 	jz	short wa0 ; nothing to wakeup
  2244                              <1> 	;
  2245 00004E5D 30E4                <1> 	xor	ah, ah
  2246 00004E5F 8825[EC6E0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2247 00004E65 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2248                              <1> 	; 15/09/2015
  2249 00004E67 0FB6D8              <1> 	movzx	ebx, al
  2250 00004E6A 88A3[EF6B0000]      <1> 	mov	[ebx+p.waitc-1], ah ; 0
  2251 00004E70 FEC4                <1> 	inc	ah
  2252 00004E72 88A3[0F6C0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2253                              <1> 	;
  2254 00004E78 57                  <1> 	push	edi
  2255 00004E79 52                  <1> 	push	edx
  2256 00004E7A E84BFFFFFF          <1> 	call	putlu
  2257 00004E7F 5A                  <1> 	pop	edx
  2258 00004E80 5F                  <1> 	pop	edi
  2259                              <1> wa0:
  2260 00004E81 C3                  <1> 	retn
  2261                              <1> 
  2262                              <1> 	; 05/12/2021
  2263                              <1> 	; 30/11/2021 - Retro UNIX 386 v1.2
  2264                              <1> sleep: 
  2265                              <1> 	; 15/09/2015
  2266                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2267                              <1> 	;
  2268                              <1> 	; 09/05/2013 - 20/03/2014
  2269                              <1> 	;
  2270                              <1> 	; Retro UNIX 8086 v1 modification !
  2271                              <1> 	; (Process/task switching and quit routine by using
  2272                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2273                              <1> 	;
  2274                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2275                              <1> 	; tty and tape output or input becomes available
  2276                              <1> 	; and process is put on waiting channel and swapped out,
  2277                              <1> 	; then -when the tty or tape is ready to write or read-
  2278                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2279                              <1> 	;
  2280                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2281                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2282                              <1> 	; status of the current process also INT 1Ch will count down
  2283                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2284                              <1> 	; to tty buffer of the current process and kernel will get
  2285                              <1> 	; user input by using tty buffer of the current process
  2286                              <1> 	; (instead of standard INT 16h interrupt).
  2287                              <1> 	; TTY output will be redirected to related video page of text mode
  2288                              <1> 	; (INT 10h will be called with different video page depending
  2289                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2290                              <1> 	; pseudo screens.)
  2291                              <1> 	;
  2292                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2293                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2294                              <1> 	; characters/data on serial port(s).
  2295                              <1> 	;
  2296                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2297                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2298                              <1> 	; 
  2299                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2300                              <1> 	;
  2301                              <1> 	;; 05/10/2013
  2302                              <1>         ;10/12/2013
  2303                              <1> 	;cmp   byte [u.uno], 1
  2304                              <1>         ;ja    short sleep0
  2305                              <1> 	;retn
  2306                              <1> 
  2307                              <1> 	; 20/03/2014
  2308                              <1> 	;mov	bx, [runq]
  2309                              <1> 	;cmp	bl, bh
  2310                              <1> 	;jne	short sleep0	
  2311                              <1> 	; 25/02/2014
  2312                              <1> 	;cmp	word ptr [runq], 0
  2313                              <1> 	;ja	short sleep0	
  2314                              <1> 	;retn
  2315                              <1> sleep0:
  2316                              <1> 	;
  2317 00004E82 E851000000          <1> 	call	isintr
  2318                              <1> 	;jnz	sysret
  2319                              <1> 		; / wait for event
  2320                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2321                              <1> 			      ; / or quit from user
  2322                              <1>                		; br 2f / something happened
  2323                              <1> 			      ; / yes, his interrupt so return
  2324                              <1>                      	      ;	/ to user
  2325                              <1> 	; 05/12/2021
  2326 00004E87 7405                <1> 	jz	short sleep_2
  2327                              <1> sleep_3:
  2328 00004E89 E93EEDFFFF          <1> 	jmp	sysret
  2329                              <1> sleep_2:
  2330                              <1> 	; 30/06/2015
  2331 00004E8E 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2332 00004E91 81C3[086E0000]      <1> 	add	ebx, wlist
  2333 00004E97 8A03                <1> 	mov	al, [ebx]
  2334 00004E99 20C0                <1> 	and	al, al
  2335 00004E9B 7407                <1> 	jz	short sleep1
  2336 00004E9D 53                  <1> 	push	ebx
  2337 00004E9E E827FFFFFF          <1> 	call	putlu
  2338 00004EA3 5B                  <1> 	pop	ebx
  2339                              <1> sleep1:
  2340 00004EA4 A0[F56E0000]        <1> 	mov	al, [u.uno]    
  2341 00004EA9 8803                <1>   	mov	[ebx], al 	; put the process number
  2342                              <1> 				; in the wait channel
  2343                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2344                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2345                              <1> 				     ; / on the stack
  2346                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2347                              <1> 				     ; / to put to sleep in there
  2348                              <1> 	; 30/11/2021
  2349 00004EAB 31DB                <1> 	xor	ebx, ebx
  2350 00004EAD 8A1D[856E0000]      <1> 	mov	bl, [cdev]
  2351 00004EB3 53                  <1> 	push	ebx
  2352                              <1>         ; 15/09/2015
  2353                              <1> 	;movzx	ebx, al
  2354 00004EB4 88C3                <1> 	mov	bl, al
  2355 00004EB6 C683[0F6C0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2356 00004EBD FEC4                <1> 	inc	ah
  2357 00004EBF 88A3[EF6B0000]      <1> 	mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2358                              <1> 	;
  2359                              <1> 	;push	word [cdev]
  2360                              <1> 	;	; mov cdev,-(sp) / nothing happened in isintr so
  2361 00004EC5 E833FEFFFF          <1> 	call	swap
  2362                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2363                              <1>         ;pop	word [cdev]
  2364                              <1> 	;	; mov (sp)+,cdev / restore device
  2365                              <1> 	; 30/11/2021
  2366 00004ECA 58                  <1> 	pop	eax
  2367 00004ECB A2[856E0000]        <1> 	mov	[cdev], al
  2368 00004ED0 E803000000          <1> 	call	isintr
  2369                              <1> 	; 22/09/2013
  2370                              <1> 	;jnz	sysret         
  2371                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2372                              <1>                		; br 2f / yes, return to new user
  2373                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2374                              <1> 				; / originally on the wait channel
  2375                              <1>        		; beq 1f / if 0 branch
  2376                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2377                              <1>        		; mov $300,*$ps / processor priority = 6
  2378                              <1> 		; jsr r0,putlu / create link to old process number
  2379                              <1>        		; clr *$ps / clear the status; process priority = 0
  2380                              <1> 	; 05/12/2021
  2381 00004ED5 75B2                <1> 	jnz	short sleep_3 ; jump to sysret
  2382                              <1>      ;1:
  2383 00004ED7 C3                  <1> 	retn
  2384                              <1> 		; rts r0 / return
  2385                              <1>      ;2:
  2386                              <1>         ;;jmp	sysret
  2387                              <1> 		; jmp sysret / return to user
  2388                              <1> 
  2389                              <1> isintr:
  2390                              <1> 	; 30/11/2021	
  2391                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2392                              <1> 	;
  2393                              <1> 	; 09/05/2013 - 30/05/2014
  2394                              <1> 	;
  2395                              <1> 	; Retro UNIX 8086 v1 modification !
  2396                              <1> 	; (Process/task switching and quit routine by using
  2397                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2398                              <1> 	;
  2399                              <1> 	; Retro UNIX 8086 v1 modification:
  2400                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2401                              <1> 	;  and there is a 'quit' request by user;
  2402                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2403                              <1> 	;  "nothing to do". (20/10/2013)
  2404                              <1> 	;
  2405                              <1> 	; 20/10/2013
  2406 00004ED8 66833D[DA6E0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2407 00004EE0 761F                <1> 	jna	short isintr2 ; retn
  2408                              <1> 	; 03/09/2013
  2409                              <1> 	; (nothing to do)
  2410                              <1> 	;retn
  2411                              <1> 	; 22/09/2013
  2412 00004EE2 66833D[F06E0000]00  <1> 	cmp	word [u.intr], 0
  2413 00004EEA 7615                <1> 	jna	short isintr2 ; retn
  2414                              <1> 	; 30/05/2014
  2415                              <1> 	;push	ax
  2416 00004EEC 50                  <1> 	push	eax ; 30/11/2021 
  2417 00004EED 66A1[F26E0000]      <1> 	mov	ax, [u.quit]
  2418 00004EF3 6609C0              <1> 	or	ax, ax ; 0 ?
  2419 00004EF6 7408                <1> 	jz	short isintr1 ; zf = 1
  2420 00004EF8 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2421 00004EFC 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2422                              <1> 	;xor	ax, ax ; zf = 1
  2423                              <1> 	; 30/11/2021
  2424 00004EFE 31C0                <1> 	xor	eax, eax
  2425                              <1> isintr1:
  2426                              <1> 	;pop	ax
  2427                              <1> 	; 30/11/2021
  2428 00004F00 58                  <1> 	pop	eax
  2429                              <1> isintr2: ; 22/09/2013
  2430                              <1> 	; zf=1 -> nothing to do
  2431 00004F01 C3                  <1> 	retn
  2432                              <1> 
  2433                              <1> 	; UNIX v1 original 'isintr' routine... 
  2434                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2435                              <1>        	;mov     r2,-(sp) / save r2
  2436                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2437                              <1>         ;                 / typewriter
  2438                              <1>        	;beq     1f / if 0, do nothing except skip return
  2439                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2440                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2441                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2442                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2443                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2444                              <1>         ;              / of interrupts
  2445                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2446                              <1>      ;1:
  2447                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2448                              <1>      ;4:
  2449                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2450                              <1>        	;mov     (sp)+,r1
  2451                              <1>        	;rts     r0
  2452                              <1>      ;3: / interrupt char = quit (fs)
  2453                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2454                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2455                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2456                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2457                              <1>      ;1: / find process control tty entry in tty block
  2458                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2459                              <1>        	;beq     1f / block found go to 1f
  2460                              <1>        	;add     $8,r1 / look at next tty block
  2461                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2462                              <1>        	;blo     1b / no
  2463                              <1>        	;br      4b / no process control tty found so go to 4b
  2464                              <1>      ;1:
  2465                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2466                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2467                              <1>         ;                  / identifier
  2468                              <1>        	;inc     0f / increment
  2469                              <1>      ;1:
  2470                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2471                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2472                              <1>         ;             / being typed out after you hit the interrupt
  2473                              <1>         ;             / key
  2474                              <1>        	;br      1b
  2080                                  %include 'u5.s'      ; 03/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) - SYS5.INC
  2085                              <1> ; Last Modification: 10/01/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 - U5.AS M (07/08/2013) //// UNIX v1 -> u5.s
  2096                              <1> ;
  2097                              <1> ; ****************************************************************************
  2098                              <1> 
  2099                              <1> 	; 09/01/2022
  2100                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2101                              <1> mget_w:
  2102                              <1> 	; 28/10/2021
  2103                              <1> 	; 22/08/2021
  2104                              <1> 	; 20/08/2021
  2105                              <1> 	; 25/05/2020
  2106                              <1> 	; 24/05/2020 - Retro UNIX 386 v2	
  2107 00004F02 C605[3A6F0000]01    <1> 	mov	byte [mget_rw], 1 ; write access
  2108 00004F09 EB07                <1> 	jmp	short mget
  2109                              <1> mget_r:
  2110                              <1> 	; 28/10/2021
  2111                              <1> 	; 22/08/2021
  2112                              <1> 	; 25/05/2020
  2113                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2114 00004F0B C605[3A6F0000]00    <1> 	mov	byte [mget_rw], 0 ; read access	
  2115                              <1> mget:
  2116                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2117                              <1> 	; 28/11/2021
  2118                              <1> 	; 22/11/2021
  2119                              <1> 	; 28/10/2021 - temporary (simplified code)
  2120                              <1> 	; 22/08/2021
  2121                              <1> 	; 20/08/2021
  2122                              <1> 	; 25/05/2020
  2123                              <1> 	; 24/05/2020
  2124                              <1> 	; 05/05/2020
  2125                              <1> 	; 02/05/2020, 03/05/2020
  2126                              <1> 	; 29/04/2020 - Retro UNIX 386 v2
  2127                              <1> 	; New inode model/format (Modified UNIX v7 inode model)
  2128                              <1> 	;	
  2129                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2130                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2131                              <1> 	;
  2132                              <1> 	; Get existing or (allocate) a new disk block for file
  2133                              <1> 	; 
  2134                              <1> 	; INPUTS ->
  2135                              <1> 	;    u.fofp (file offset pointer)
  2136                              <1> 	;    inode 
  2137                              <1> 	;    u.off (file offset)
  2138                              <1> 	; OUTPUTS ->
  2139                              <1> 	;    r1 (physical block number)
  2140                              <1> 	;    r2, r3, r5 (internal)
  2141                              <1> 	;
  2142                              <1> 	; ((AX = R1)) output
  2143                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2144                              <1> 	;
  2145                              <1> 	; Modified registers: eax, edx, ebx, ecx, esi, edi, ebp
  2146                              <1> 
  2147                              <1> 	; Retro UNIX 386 v2 'mget' procedure
  2148                              <1> 	; source code reference:
  2149                              <1> 	; 'mget' procedure in UNIXHDCP.ASM (25/01/2020) by Erdogan Tan
  2150                              <1> 
  2151                              <1> 	; Get sector/block address for current file pointer
  2152                              <1> 	; (If file pointer points to a number greater than current file
  2153                              <1> 	; size, a new -empty- sector/block will be created/written.)
  2154                              <1> 
  2155                              <1> 	; Note: 'mget' procedure will be used for only RUNIX v2 FS.
  2156                              <1> 	;	(installable file system drivers will not use 'mget')
  2157                              <1> 	;	 !!! 512 bytes per sector !!!  ; 02/05/2020
  2158                              <1> 
  2159                              <1> 	; ! 64 bit fofp ! but Retro UNIX 386 v2 kernel will use 32 bit
  2160                              <1> 	; file offset for regular files and directories.
  2161                              <1> 	; ('mget' procedure will be called for regular files & directories)
  2162                              <1> 
  2163                              <1> 	; 28/10/2021
  2164                              <1> 	; Note: 'mget' uses only current inode ([ii], 'inode:')
  2165                              <1> 	; (inode must be loaded at 'inode:' addr by 'iget' before 'mget')  
  2166                              <1> 
  2167                              <1> 		; mov *u.fofp,mq / file offset in mq
  2168                              <1> 		; clr ac / later to be high sig
  2169                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2170                              <1> 		; mov mq,r2
  2171                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2172                              <1> 		; bne 4f / branch for large file
  2173                              <1> 
  2174                              <1> 	; 09/01/2022
  2175                              <1> 	; Return: eax = physical block/sector number
  2176                              <1> mget_0:	
  2177 00004F12 8B35[B86E0000]      <1>         mov     esi, [u.fofp]
  2178 00004F18 8B1E                <1> 	mov	ebx, [esi]
  2179                              <1>         ; ebx = file offset
  2180                              <1> 
  2181                              <1> 	; 20/08/2021
  2182 00004F1A C1EB09              <1> 	shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2183                              <1> 
  2184 00004F1D F605[416B0000]10    <1> 	test	byte [i.flgs+1], 10h ; is this a large or small file addr?
  2185 00004F24 7405                <1> 	jz	short mget_1 ; small file addressing
  2186 00004F26 E986000000          <1> 	jmp	mget_5	; large file addressing
  2187                              <1> mget_1:
  2188                              <1> 	; If large file flag is clear -not set- RUNIX v2 FS inode
  2189                              <1> 	; will contain 10 direct disk block/sector dword pointers.
  2190                              <1> 
  2191                              <1> 	; 05/05/2020
  2192                              <1> 	;shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2193                              <1> 
  2194 00004F2B 83FB0A              <1> 	cmp	ebx, 10	; block 10
  2195 00004F2E 733A                <1> 	jnb	short mget_3 ; file offset >= 5120
  2196                              <1> 
  2197                              <1> 	; 05/05/2020
  2198                              <1> 	;cmp	ebx, 5120
  2199                              <1> 	;jnb	short mget_3 ; file offset >= 5120
  2200                              <1> 
  2201                              <1> 	;mov	bl, bh
  2202                              <1> 	;and	bl, 1Eh ; clear all bits but bits 1,2,3,4 ; 0,2,..,18
  2203                              <1> 	;	; max. value = 12h = 10010b = 18 (because ebx <= 5119) 
  2204                              <1> 	;shl	bl, 1	; * 2 ; max. value = 24h = 100100b = 36
  2205                              <1> 	;xor	bh, bh  ; clear bh
  2206                              <1> 		; RUNIX v2 (RUFS 2) file system bytes per sector value
  2207                              <1> 		; is always 512.
  2208                              <1> 		; ebx = 4*(ebx/512)  = 0 to 36
  2209                              <1> 
  2210                              <1> 	; 05/05/2020
  2211 00004F30 C0E302              <1> 	shl	bl, 2 ; * 4
  2212                              <1> 		 ; ebx = 0 to 36
  2213                              <1> 
  2214 00004F33 8B83[4C6B0000]      <1> 	mov	eax, [ebx+i.dskp] ; disk sector addr ptr 0 to 9 for file
  2215                              <1> 	; 22/08/2021
  2216 00004F39 89DE                <1> 	mov	esi, ebx
  2217                              <1> 	;xor	ebx, ebx ; 0
  2218                              <1> 	; 09/01/2022
  2219 00004F3B 30DB                <1> 	xor	bl, bl
  2220                              <1> 
  2221 00004F3D 09C0                <1> 	or	eax, eax
  2222 00004F3F 7512                <1> 	jnz	short mget_2 ; existing block/sector (logical)
  2223                              <1> 
  2224 00004F41 56                  <1> 	push	esi ; * ; 22/08/2021
  2225 00004F42 E877010000          <1> 	call	alloc_m ; 24/05/2020	
  2226                              <1> 	;call	alloc	; allocate a new sector/block for this file	
  2227                              <1> 			; eax = sector/block number
  2228                              <1> 			; ebx = buffer header address
  2229 00004F47 5E                  <1> 	pop	esi ; * ; 22/08/2021
  2230                              <1> 	; 28/11/2021
  2231                              <1> 	;jc	short mget_2 
  2232                              <1> 			; cf = 1 -> eax = 'no free block' error
  2233                              <1> 	; 22/08/2021
  2234 00004F48 8986[4C6B0000]      <1> 	mov	[esi+i.dskp], eax  ; logical sector/block address
  2235                              <1> 
  2236                              <1> 	; 09/01/2022
  2237 00004F4E E8BC040000          <1> 	call	setimod	; set inode modification flag
  2238                              <1> 			; and set modification time
  2239                              <1> 
  2240                              <1> 	; eax = logical sector/block number
  2241                              <1> 	; ([idev] = logical drive number)
  2242                              <1> 	; 28/10/2021
  2243                              <1> 	; [cdev] = logical drive number (0 or 1)
  2244                              <1> 	;	(0 = root fs, 1 = mounted fs)
  2245                              <1> mget_2:
  2246                              <1> 	; 09/01/2022
  2247                              <1> 	; eax = logical sector/block number
  2248 00004F53 F605[856E0000]01    <1> 	test	byte [cdev], 1
  2249 00004F5A 7507                <1> 	jnz	short mget_14
  2250                              <1> 	; convert to physical sector/block number
  2251 00004F5C 0305[586F0000]      <1> 	add	eax, [systm+SB.BootSectAddr]
  2252 00004F62 C3                  <1> 	retn
  2253                              <1> 	; 09/01/2022
  2254                              <1> mget_14:
  2255                              <1> 	; convert to physical sector/block number
  2256 00004F63 0305[60710000]      <1> 	add	eax, [mount+SB.BootSectAddr]
  2257 00004F69 C3                  <1> 	retn
  2258                              <1> 	
  2259                              <1> 		; rts r0
  2260                              <1> mget_3: ; 3: / adding on block which changes small file to a large file
  2261                              <1> 	; 22/11/2021
  2262 00004F6A E84F010000          <1> 	call	alloc_m ; 24/05/2020
  2263                              <1> 	;call	alloc	; allocate a new sector/block for this file
  2264                              <1> 			; eax = sector/block number
  2265                              <1> 			; ebx = buffer header  ; 24/05/2020
  2266                              <1> 	; 28/11/2021
  2267                              <1> 	;jc	short mget_2 ; error code in eax
  2268                              <1> 
  2269                              <1> 	; 09/01/2022
  2270                              <1> 	; convert to physical block/sector number
  2271 00004F6F 50                  <1> 	push	eax ; *!* ; logical sector/block number 
  2272 00004F70 E8DEFFFFFF          <1> 	call	mget_2
  2273                              <1> 
  2274                              <1>         ; EAX (r1) = Physical block (sector) number
  2275 00004F75 E807100000          <1> 	call 	wslot
  2276                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2277                              <1> 			     ; / first data word in buffer
  2278                              <1>         ; EAX (r1) = Physical block number
  2279                              <1> 	; 28/11/2021
  2280                              <1> 	; ebx = buffer (data) address
  2281                              <1> 	; 22/11/2021
  2282 00004F7A 31C9                <1> 	xor	ecx, ecx
  2283 00004F7C B10A                <1> 	mov 	cl, 10	; r3, transfer old physical block pointers
  2284                              <1> 			; into new indirect block area for the new
  2285                              <1> 			; large file		
  2286 00004F7E 89DF                <1> 	mov 	edi, ebx ; r5
  2287 00004F80 BE[4C6B0000]        <1> 	mov	esi, i.dskp  ; current inode's direct disk addr ptrs
  2288 00004F85 89C2                <1> 	mov	edx, eax
  2289 00004F87 31C0                <1> 	xor	eax, eax
  2290                              <1> mget_4:
  2291 00004F89 A5                  <1> 	movsd 	
  2292 00004F8A 8946FC              <1> 	mov	[esi-4], eax ; 0
  2293 00004F8D E2FA                <1> 	loop	mget_4
  2294                              <1> 
  2295                              <1> 	; 22/11/2021
  2296 00004F8F B176                <1> 	mov 	cl, 128-10 ; clear rest of data buffer
  2297                              <1> ;mget_4: ; 1
  2298 00004F91 F3AB                <1> 	rep 	stosd
  2299                              <1> 		; clr (r5)+
  2300                              <1> 		; dec r3
  2301                              <1> 		; bgt 1b
  2302 00004F93 89D0                <1> 	mov	eax, edx
  2303                              <1>         ; EAX (r1) = Physical block number
  2304 00004F95 E803100000          <1> 	call	dskwr
  2305                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2306                              <1> 
  2307                              <1> 	;; EAX (r1) = Physical block number
  2308                              <1> 
  2309                              <1> 	; 09/01/2022        
  2310 00004F9A 8F05[4C6B0000]      <1> 	pop	dword [i.dskp] ; *!* ; logical sector/block number
  2311                              <1>  
  2312                              <1> 	; eax = logical disk sector/block number/addr ; 09/01/2022
  2313                              <1> 	;mov 	[i.dskp], eax ; 22/11/2021 
  2314                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2315                              <1> 
  2316 00004FA0 800D[416B0000]10    <1> 	or	byte [i.flgs+1], 10000b ; 10h ; 16  ; large file flag
  2317                              <1> 		; bis $10000,i.flgs / set large file bit 
  2318                              <1> 				  ; / in i.flgs word of i-node
  2319 00004FA7 E863040000          <1> 	call	setimod
  2320                              <1> 		; jsr r0,setimod / set i-node modified flag
  2321                              <1> 
  2322 00004FAC E961FFFFFF          <1> 	jmp	mget_0 ; 09/01/2022
  2323                              <1> 		; br mget
  2324                              <1> 
  2325                              <1> mget_5:  ; 4 ; large file
  2326                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2327                              <1> 	;
  2328                              <1> 	; Retro UNIX 386 v2 disk inode contains..
  2329                              <1> 	; (if large file flag is set)
  2330                              <1> 	; 8 indirect disk block/sector dword pointers
  2331                              <1> 	; +1 double indirect disk block/sector dword pointers
  2332                              <1> 	; +1 triple indirect disk block/sector dword pointers
  2333                              <1> 
  2334                              <1> 	; check indirect pointers limit (as file offset)
  2335                              <1> 	; 8*128 = 1024 blocks (or sectors) or 512 KB
  2336                              <1> 	; check dx (file offset hw) value
  2337                              <1> 	
  2338                              <1> 	; 03/05/2020
  2339                              <1> 	;cmp	ebx, 524288  ; is file offset >= 524288 ?
  2340                              <1> 	;jnb	short mget_6 ; yes, check double indirect limit
  2341                              <1> 
  2342                              <1> 	; 05/05/2020
  2343 00004FB1 81FB00040000        <1> 	cmp	ebx, 1024    ; block 1024 (byte 524288)	
  2344 00004FB7 7321                <1> 	jnb	short mget_6 ; check double indirect limit
  2345                              <1> 
  2346 00004FB9 C605[3C6F0000]01    <1> 	mov	byte [level], 1 ; levels, 1 = indirect blocks
  2347                              <1> 
  2348                              <1> 	; 05/05/2020
  2349                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2350                              <1> 
  2351 00004FC0 88D9                <1> 	mov	cl, bl
  2352 00004FC2 80E17F              <1> 	and	cl, 127
  2353 00004FC5 880D[3D6F0000]      <1> 	mov	[level+1], cl ; level 1, direct block ptr index (0 to 127)
  2354 00004FCB 66C1EB07            <1> 	shr	bx, 7 ; bl = level 0, indirect block pointer index (0 to 7)
  2355                              <1> 	;mov	[level+2], bl
  2356                              <1> 
  2357 00004FCF C0E302              <1> 	shl	bl, 2 ; * 4 to convert index number to offset
  2358                              <1> 
  2359                              <1> 	;mov	esi, i.dskp
  2360                              <1> 	;add	esi, ebx
  2361                              <1> 
  2362 00004FD2 8DB3[4C6B0000]      <1> 	lea	esi, [ebx+i.dskp]
  2363                              <1> 
  2364 00004FD8 EB66                <1> 	jmp	short mget_8
  2365                              <1> 
  2366                              <1> mget_6:
  2367                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2368                              <1> 	; 03/05/2020
  2369                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2370                              <1> 	; check double indirect pointer limit (as file offset)
  2371                              <1> 	; (128*128)+1024 = 16384+1024 blocks or 8 MB + 512 KB
  2372                              <1> 	; check dx (file offset hw) value
  2373                              <1> 	
  2374                              <1> 	;cmp	ebx, 8912896 ; >= 17408 sectors (16384+1024) ?	
  2375                              <1> 	;jnb	short mget_7 ; yes, use triple indirect pointer (block)
  2376                              <1> 
  2377                              <1> 	; 05/05/2020
  2378 00004FDA 81FB00440000        <1> 	cmp	ebx, 17408   ; block 17408 (byte 8912896)	
  2379 00004FE0 7329                <1> 	jnb	short mget_7 ; use triple indirect pointer (block)
  2380                              <1> 
  2381 00004FE2 C605[3C6F0000]02    <1> 	mov	byte [level], 2  ; levels, 2 = double indirect blocks
  2382                              <1> 	
  2383                              <1> 	;sub	ebx, 524288 ; 1024 sectors
  2384                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2385                              <1> 			; (from sector 1024)
  2386                              <1> 	; 05/05/2020
  2387 00004FE9 81EB00040000        <1> 	sub	ebx, 1024 ; offset from sector 1024
  2388                              <1> 	
  2389 00004FEF 88D9                <1> 	mov	cl, bl
  2390 00004FF1 80E17F              <1> 	and	cl, 127
  2391 00004FF4 880D[3D6F0000]      <1> 	mov	[level+1], cl
  2392                              <1> 			; level 2, direct block ptr index (0 to 127)	
  2393 00004FFA 66C1EB07            <1> 	shr	bx, 7
  2394 00004FFE 881D[3E6F0000]      <1> 	mov	[level+2], bl
  2395                              <1> 			; level 1, indirect block ptr index (0 to 127)
  2396                              <1> 
  2397 00005004 BE[6C6B0000]        <1> 	mov	esi, i.dskp + 32 ; 8*4
  2398                              <1> 			; level 0, double indirect block pointer
  2399 00005009 EB35                <1> 	jmp	short mget_8
  2400                              <1> 
  2401                              <1> mget_7:
  2402                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2403                              <1> 	; 03/05/2020
  2404                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2405                              <1> 	; triple indirect pointer ; 8912896 to 1082654720 bytes
  2406                              <1> 	;mov	esi, i.dskp + 36 ; 9*4
  2407                              <1> 
  2408 0000500B C605[3C6F0000]03    <1> 	mov	byte [level], 3  ; levels, 3 = triple indirect blocks
  2409                              <1> 
  2410                              <1> 	;sub	ebx, 8912896 ; 17408 sectors (16384+1024)
  2411                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2412                              <1> 			; (from sector 17408)
  2413                              <1> 	; 05/05/2020
  2414 00005012 81EB00440000        <1> 	sub	ebx, 17408 ; offset from sector 17408	
  2415                              <1> 
  2416 00005018 88D9                <1> 	mov	cl, bl
  2417 0000501A 80E17F              <1> 	and	cl, 127
  2418 0000501D 880D[3D6F0000]      <1> 	mov	[level+1], cl  
  2419                              <1> 			; level 3, direct block ptr index (0 to 127)	
  2420 00005023 C1EB07              <1> 	shr	ebx, 7	
  2421 00005026 88D9                <1> 	mov	cl, bl
  2422 00005028 80E17F              <1> 	and	cl, 127
  2423 0000502B 880D[3E6F0000]      <1> 	mov	[level+2], cl
  2424                              <1> 			; level 2, indirect block ptr index (0 to 127)
  2425 00005031 66C1EB07            <1> 	shr	bx, 7
  2426 00005035 881D[3F6F0000]      <1> 	mov	[level+3], bl
  2427                              <1> 			; level 1, double indir blk ptr index (0 to 127)
  2428                              <1> 
  2429 0000503B BE[706B0000]        <1> 	mov	esi, i.dskp + 36 ; 9*4
  2430                              <1> 			; level 0, triple indirect block pointer
  2431                              <1> mget_8:
  2432                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibiliy modification
  2433 00005040 8B06                <1> 	mov	eax, [esi]
  2434 00005042 09C0                <1> 	or 	eax, eax ; R1
  2435 00005044 751A                <1> 	jnz 	short mget_10 ; 2f
  2436                              <1> 		; bne 2f / if no indirect block exists
  2437 00005046 56                  <1> 	push	esi	; * ; 24/05/2020
  2438                              <1> 
  2439 00005047 E872000000          <1> 	call	alloc_m ; 24/05/2020
  2440                              <1> 	;call	alloc	; allocate a new block for this file	
  2441                              <1> 			; eax = block number
  2442                              <1> 			; ebx = buffer header address
  2443                              <1> 			; [pdn] = physical drive number ; 25/05/2020
  2444                              <1> 	;jc	mget_2	; cf -> 1 & eax = 0 -> no free block
  2445                              <1> 
  2446 0000504C 5E                  <1> 	pop	esi	; * ; 24/05/2020
  2447                              <1> 	;jc	short mget_9
  2448                              <1> 
  2449                              <1> 	; 09/01/2022
  2450                              <1> 	; eax = logical sector/block number
  2451                              <1> 
  2452 0000504D 8906                <1> 	mov	[esi], eax ; record sector/block address on i.dskp area
  2453                              <1> 
  2454 0000504F E8BB030000          <1> 	call 	setimod
  2455                              <1> 		; jsr r0,setimod / set i-node modified byte
  2456                              <1> 	; EAX = new block number (logical)
  2457                              <1> 
  2458                              <1> 	; 09/01/2022
  2459                              <1> 	; convert to physical block/sector number
  2460 00005054 E8FAFEFFFF          <1> 	call	mget_2
  2461                              <1> 	;
  2462 00005059 E89BFDFFFF          <1> 	call 	clear
  2463                              <1> 		; jsr r0,clear / clear new block
  2464                              <1> 	; 22/11/2021
  2465 0000505E EB0A                <1> 	jmp	short mget_11
  2466                              <1> ;mget_9:
  2467                              <1> ;	pop	edx ; *  ; 09/01/2022
  2468                              <1> ;	retn
  2469                              <1> mget_10: ;2
  2470                              <1> 	; 09/01/2022
  2471                              <1> 	; eax = logical sector/block number/address
  2472                              <1> 	; convert to physical sector/block number/address
  2473 00005060 E8EEFEFFFF          <1> 	call	mget_2	
  2474                              <1> 	; 05/03/2013
  2475                              <1> 	; EAX = r1, physical block number (of indirect block)
  2476 00005065 E8B70E0000          <1> 	call 	dskrd ; read indirect block
  2477                              <1> 		; jsr r0,dskrd / read in indirect block
  2478                              <1> 	;jc	short mget_9
  2479                              <1> mget_11:
  2480                              <1> 	; 22/11/2021
  2481                              <1> 	; eax = physical block/sector address
  2482                              <1> 	; ebx = buffer address
  2483                              <1> 
  2484 0000506A 89C2                <1> 	mov	edx, eax ; *  ; save physical sector number in edx
  2485                              <1> 
  2486 0000506C 0FB605[3C6F0000]    <1> 	movzx	eax, byte [level]
  2487 00005073 8A80[3C6F0000]      <1> 	mov	al, [eax+level] ; get sector pointer offset
  2488 00005079 C1E002              <1> 	shl	eax, 2 ; * 4 ; 09/01/2022
  2489                              <1> 	;shl	ax, 2 ; * 4
  2490                              <1> 
  2491 0000507C 01C3                <1> 	add	ebx, eax
  2492                              <1> 
  2493 0000507E 8B03                <1> 	mov 	eax, [ebx] ; put logical block no of block
  2494                              <1> 			   ; in file sought in R1 (EAX)
  2495                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2496                              <1> 	               	    ; / sought in r1
  2497                              <1> 
  2498 00005080 21C0                <1> 	and	eax, eax  ; if logical sector/block number is zero
  2499                              <1> 			  ; then we need a new block for file
  2500 00005082 740F                <1> 	jz	short mget_12
  2501                              <1> 
  2502 00005084 FE0D[3C6F0000]      <1> 	dec	byte [level]
  2503 0000508A 75D4                <1> 	jnz	short mget_10
  2504                              <1> 
  2505 0000508C 29DB                <1> 	sub	ebx, ebx ; ebx = 0 ; existing sector
  2506                              <1> 
  2507                              <1> 	;retn
  2508                              <1> 	; 09/01/2022
  2509                              <1> 	; eax = logical block/sector number
  2510 0000508E E9C0FEFFFF          <1> 	jmp	mget_2
  2511                              <1> 
  2512                              <1> mget_12:
  2513                              <1> 	; 22/11/2021
  2514 00005093 52                  <1> 	push	edx ; *
  2515 00005094 53                  <1> 	push	ebx ; ** ; buffer data position
  2516 00005095 E824000000          <1> 	call	alloc_m
  2517                              <1> 	;call	alloc	 ; allocate a new block for this file	
  2518                              <1> 			 ; eax = block number (logical)
  2519                              <1> 			 ; ebx = buffer header address
  2520 0000509A 5E                  <1> 	pop	esi ; **
  2521                              <1> 	; 09/01/2022
  2522                              <1> 	;pop	edx ; *
  2523                              <1> 	;jc	short mget_9 ; cf -> 1 & eax = 0 -> no free block
  2524                              <1> 
  2525 0000509B 8906                <1> 	mov	[esi], eax ; record/save block number (logical)
  2526                              <1> 
  2527                              <1> 	; 22/11/2021
  2528 0000509D 870424              <1> 	xchg	eax, [esp] ; *
  2529                              <1> 
  2530                              <1> 	; eax (r1) = physical block number (of indirect block)
  2531 000050A0 E8DC0E0000          <1> 	call 	wslot
  2532                              <1> 		; jsr r0,wslot
  2533                              <1>         ; eax (r1) = physical block number
  2534                              <1> 	; ebx (r5) = pointer to buffer (indirect block)
  2535 000050A5 E8F30E0000          <1> 	call 	dskwr
  2536                              <1> 	; eax = r1 = physical block number (of indirect block)
  2537                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2538                              <1> 			     ; / back out on disk
  2539 000050AA 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2540                              <1> 		; mov (sp),r1 / restore block number of new block	
  2541                              <1> 
  2542                              <1> 	; 09/01/2022
  2543                              <1> 	; eax = logical sector/block number/address of new block
  2544                              <1> 	; convert to physical sector/block number/address
  2545 000050AB E8A3FEFFFF          <1> 	call	mget_2	
  2546                              <1> 
  2547 000050B0 E844FDFFFF          <1> 	call 	clear
  2548                              <1> 		; jsr r0,clear / clear new block
  2549                              <1> 
  2550 000050B5 FE0D[3C6F0000]      <1> 	dec	byte [level]
  2551 000050BB 75AD                <1> 	jnz	short mget_11
  2552                              <1> 
  2553                              <1> 	; 09/01/2022
  2554                              <1> 	; eax = physical sector/block number/address of new block
  2555                              <1> 	
  2556                              <1> 	; 22/11/2021
  2557                              <1> 	; ebx = buffer address
  2558                              <1> mget_13: ; 2
  2559                              <1> 	; eax (r1) = Block number of new block
  2560 000050BD C3                  <1> 	retn
  2561                              <1> 		; rts r0
  2562                              <1> 
  2563                              <1> 	; 09/01/2022
  2564                              <1> 	; 26/11/2021
  2565                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2566                              <1> alloc_m:
  2567                              <1> 	; 27/11/2021
  2568                              <1> 	; 28/10/2021
  2569                              <1> 	; 07/05/2021
  2570                              <1> 	; 26/05/2020
  2571                              <1> 	; 25/05/2020
  2572                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2573                              <1> 	; 'alloc' call in 'mget'
  2574                              <1> 	;
  2575                              <1> 	; (('mget_r' will be returned with error))
  2576                              <1> 	; (('mget_w' will continue to 'alloc'))
  2577                              <1> 
  2578                              <1> 	; Note: 'sysread' will return with cf = 0, eax = 0
  2579                              <1> 	; if [fofp] >= file size (eax = 0 --> EOF)
  2580                              <1> 	; So, if we are here, that means [fofp] < file size
  2581                              <1> 	;     but disk address is 0. 
  2582                              <1> 	
  2583 000050BE 803D[3A6F0000]01    <1> 	cmp	byte [mget_rw], 1 ; write access ? (mget_w) 
  2584 000050C5 730F                <1> 	jnb	short alloc ; yes (this is a call from 'mget_w')
  2585                              <1> 	; ((cf = 1))	
  2586                              <1> 	; no (this is a call from 'mget_r') !
  2587                              <1> 	;mov	eax, ERR_FILE_SIZE ; file size error (inode error!)
  2588                              <1> 		; [User may change this empty/invalid inode (disk) sector
  2589                              <1> 		; pointer with a new valid inode (disk) sector pointer 
  2590                              <1> 		; by writing new clear (zero) sector to same file position
  2591                              <1> 		; in order to correct file size -inode parm/content- error.
  2592                              <1> 		; It may be useful for recovering lost data if other sector
  2593                              <1> 		; pointers are not empty.]	
  2594                              <1> 	;retn
  2595                              <1> 	; 27/11/2021
  2596 000050C7 C705[186F0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE 
  2596 000050CF 0000                <1>
  2597                              <1> 			; file size error (inode error!)
  2598 000050D1 E9D6EAFFFF          <1> 	jmp	error
  2599                              <1> alloc:
  2600                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2601                              <1> 	; 27/11/2021
  2602                              <1> 	; 26/11/2021 - Major modification for Runix v2 file system
  2603                              <1> 	;	(I have called this kernel version as v1.2, it is a
  2604                              <1> 	;	 debug/test version just before Retro UNIX 386 v2 kernel)
  2605                              <1> 	;	((there were running problems on new version, 
  2606                              <1> 	;	  so i am developing an intermediate version with minimum
  2607                              <1> 	;	  modification on v1.1 code which is successfuly running))
  2608                              <1> 	;	 ; /// Erdogan Tan - Istanbul, 26/11/2021 /// 
  2609                              <1> 	;	 
  2610                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2611                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2612                              <1> 	;
  2613                              <1> 	; get a free block and 
  2614                              <1> 	; set the corresponding bit in the free storage map
  2615                              <1> 	; 
  2616                              <1> 	; INPUTS ->
  2617                              <1> 	;    cdev (current device)
  2618                              <1> 	;    r2 
  2619                              <1> 	;    r3
  2620                              <1> 	; OUTPUTS ->
  2621                              <1> 	;    r1 (physical block number of block assigned)
  2622                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2623                              <1> 	;
  2624                              <1> 	; ((AX = R1)) output
  2625                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2626                              <1>         ;    ((Modified registers: edx, ecx)) 
  2627                              <1> 
  2628                              <1> 	; 26/11/2021
  2629                              <1> 	; INPUT:
  2630                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2631                              <1> 	; OUTPUT:
  2632                              <1> 	;	eax = disk block/sector number/address (physical)
  2633                              <1> 	;	(ebx = disk buffer address for sector/block in eax)
  2634                              <1> 	;
  2635                              <1> 	;    Note:	
  2636                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2637                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2638                              <1> 	;	modification flag will be set; but the superblock 
  2639                              <1> 	;	will not be written to it's disk in this 'alloc' procedure)
  2640                              <1> 	;
  2641                              <1> 	; Modified registers: eax, ebx, ecx, edx, esi, edi, ebp
  2642                              <1> 
  2643                              <1> 	; 09/01/2022
  2644                              <1> 	; Return: eax = logical block/sector number 
  2645                              <1> 
  2646                              <1> 	; 26/11/2021
  2647 000050D6 BB[546F0000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2648                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2649 000050DB F605[856E0000]01    <1> 	test	byte [cdev], 1
  2650                              <1> 		; tst cdev
  2651 000050E2 7405                <1> 	jz	short alloc_1
  2652                              <1> 		; beq 1f / drum is device
  2653 000050E4 BB[5C710000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2654                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2655                              <1> 			      ; / free storage map
  2656                              <1> alloc_1: ; 1
  2657                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2658                              <1> 	;test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2659                              <1> 	;jnz	short alloc_2  ; 'read only file system' error
  2660                              <1> 	;
  2661 000050E9 8B4B38              <1> 	mov	ecx, [ebx+SB.FreeBlocks] ; count of free blocks/sectors
  2662 000050EC 21C9                <1> 	and	ecx, ecx
  2663 000050EE 750F                <1> 	jnz	short alloc_3
  2664                              <1> alloc_2:
  2665                              <1> 	; 'no free blocks on disk !' error
  2666 000050F0 C705[186F0000]2100- <1> 	mov	dword [u.error], ERR_ALLOC
  2666 000050F8 0000                <1>
  2667 000050FA E9ADEAFFFF          <1> 	jmp	error
  2668                              <1> alloc_3:
  2669                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2670 000050FF 31C0                <1> 	xor	eax, eax
  2671                              <1> 	; 23/07/2021
  2672 00005101 8B4B3C              <1> 	mov	ecx, [ebx+SB.FirstFreeBlk] ; 1st free sector number
  2673                              <1> 					 ; (as logical sector number)
  2674 00005104 09C9                <1> 	or	ecx, ecx
  2675 00005106 7415                <1> 	jz	short alloc_5 ; 0 = initial/reset value or 'not valid'
  2676 00005108 41                  <1> 	inc	ecx ; 0FFFFFFFFh -> 0
  2677 00005109 7412                <1> 	jz	short alloc_5 ; 'not valid' or 'not calculated'
  2678 0000510B 49                  <1> 	dec	ecx ; restore first free block value
  2679 0000510C 89C8                <1> 	mov	eax, ecx
  2680                              <1> 	; 1 allocation byte (in fbm) is for 8 sectors
  2681 0000510E C1E903              <1> 	shr	ecx, 3	; first free block number / 8
  2682 00005111 80E1FC              <1> 	and	cl, ~3	; dword alignment (to backward)
  2683                              <1> 	; 27/11/2021
  2684 00005114 890D[3C6F0000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm
  2685                              <1> alloc_4:
  2686 0000511A C1E80C              <1> 	shr	eax, 12 ; 1 fbm sector for 4096 sectors
  2687                              <1> alloc_5:
  2688                              <1> 	; 26/11/2021
  2689 0000511D 53                  <1> 	push	ebx ; ** ; superblock buffer address 
  2690                              <1> 	; eax = fbm sector index
  2691 0000511E A3[406F0000]        <1> 	mov	[free_map_index], eax
  2692 00005123 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2693                              <1> 			; free blocks map start sector addr
  2694                              <1> 	; 09/01/2022
  2695 00005126 034304              <1> 	add	eax, [ebx+SB.BootSectAddr] 
  2696                              <1> 			; + Hidden Sectors
  2697                              <1> 	;
  2698                              <1> 	; eax = physical sector number
  2699 00005129 E8F30D0000          <1> 	call	dskrd
  2700                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2701                              <1> 	; eax = physical sector number
  2702                              <1> 	; ebx = buffer data address
  2703                              <1> 	; 27/11/2021
  2704 0000512E 8B15[3C6F0000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2705 00005134 A3[446F0000]        <1> 	mov	[free_map_sector], eax ; physical sector number
  2706 00005139 B9FF010000          <1> 	mov	ecx, 511
  2707                              <1> 	;and	edx, 511
  2708 0000513E 21CA                <1> 	and 	edx, ecx ; fbm byte offset in fbm buffer
  2709 00005140 41                  <1> 	inc	ecx ; 512
  2710 00005141 01D9                <1> 	add	ecx, ebx
  2711 00005143 01DA                <1> 	add	edx, ebx ; + buffer address
  2712 00005145 5B                  <1> 	pop	ebx ; ** ; superblock buffer address 
  2713                              <1> 	;
  2714                              <1> 	; ebx = superblock buffer address
  2715                              <1> 	; edx = superblock buffer address + byte offset (dword aligned)
  2716                              <1> 	; ecx = superblock buffer address + 512
  2717                              <1> alloc_6:
  2718                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2719                              <1> 	;		for Retro UNIX 386 v1.2
  2720                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 code
  2721                              <1> 	; (dword scan) ((1 dword = 32 sectors, 1 byte = 8 sectors))
  2722                              <1> 	; ((Note: Logical drive size must be multiplies of 32 sectors))
  2723                              <1> 	; 19/05/2020
  2724                              <1> 	; edx = free blocks map byte address 
  2725 00005146 0FBC02              <1> 	bsf	eax, [edx] ; Scans source operand for first bit set (1).
  2726                              <1> 			  ; Clear ZF if a bit is found set (1) and 
  2727                              <1> 			  ; loads the destination with an index to
  2728                              <1> 			  ; first set bit. (0 -> 31) 
  2729                              <1> 			  ; Sets ZF to 1 if no bits are found set.
  2730 00005149 752A                <1> 	jnz	short alloc_8 ; ZF = 0 -> a free block has been found
  2731                              <1> 
  2732 0000514B A1[3C6F0000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2733 00005150 83C004              <1> 	add	eax, 4 ; next dword
  2734 00005153 3B431C              <1> 	cmp	eax, [ebx+SB.FreeMapSize] ; fbm size in bytes
  2735 00005156 7209                <1> 	jb	short alloc_7
  2736                              <1> 	; invalidate superblock's first free block field
  2737 00005158 C7433CFFFFFFFF      <1> 	mov	dword [ebx+SB.FirstFreeBlk], 0FFFFFFFFh
  2738                              <1> 	; 'no free blocks on disk !' error
  2739 0000515F EB8F                <1> 	jmp	alloc_2
  2740                              <1> alloc_7:
  2741                              <1> 		; 26/05/2020
  2742                              <1> 		; NOTE: If ldrv size is not multiplies of 32 sectors,
  2743                              <1> 		; mod (ldrv size / 32) sectors (at the end of ldrv)
  2744                              <1> 		; can not be allocated (for regular files or dirs)! 
  2745                              <1> 		; (Kernel or runix fs installation program can use
  2746                              <1> 		;  this fact to save/duplicate critical sectors/data 
  2747                              <1> 		;  onto end sectors of that logical drive's runix fs.)
  2748                              <1> 
  2749                              <1> 	; 26/11/2021
  2750 00005161 A3[3C6F0000]        <1> 	mov	[free_map_offset], eax
  2751                              <1> 	; 28/07/2021
  2752                              <1> 	; set next first free block value for search
  2753 00005166 C1E003              <1> 	shl	eax, 3 ; * 8 ; first free block
  2754                              <1>  	; 26/11/2021
  2755 00005169 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2756                              <1> 	; search (scan) for next free block map dword (in buffer)
  2757 0000516C 83C204              <1> 	add	edx, 4 ; next dword
  2758 0000516F 39CA                <1> 	cmp	edx, ecx
  2759 00005171 72D3                <1> 	jb	short alloc_6
  2760                              <1> 	; 27/11/2021
  2761 00005173 EBA5                <1> 	jmp	short alloc_4
  2762                              <1> 
  2763                              <1> alloc_8:
  2764                              <1> 	; 26/11/2021
  2765                              <1> 	; convert bit index to xor value
  2766                              <1> 	; and then set allocated flag for corresponding fbm bit 
  2767 00005175 89C1                <1> 	mov	ecx, eax
  2768                              <1> 	;mov	cl, al 
  2769                              <1> 	;sub	eax, eax
  2770                              <1> 	;inc	al ; eax = 1
  2771 00005177 B001                <1> 	mov	al, 1
  2772 00005179 D3E0                <1> 	shl	eax, cl
  2773 0000517B 3102                <1> 	xor	[edx], eax  ; clear allocated block's bit in the fbm
  2774                              <1> 	; zero bit means allocated disk block (1 means free disk block) 
  2775                              <1> 
  2776 0000517D A1[3C6F0000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2777                              <1> 		; note: eax is dword aligned (0,4,8,12..) !
  2778 00005182 C1E003              <1> 	shl	eax, 3 ; * 8 ; free block number base
  2779 00005185 01C8                <1> 	add	eax, ecx ; add allocation bit index (0 to 31)	
  2780 00005187 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax ; current free block
  2781                              <1> 				; (which is being allocated here)
  2782                              <1> 
  2783                              <1> 	;mov	eax, [ebx+SB.FreeMapAddr] 
  2784                              <1> 	;		; free blocks map start sector addr
  2785                              <1> 	;add	eax, [free_map_index]
  2786                              <1> 	
  2787                              <1> 	;;add	eax, [ebx+SB.BootSectAddr] 
  2788                              <1> 	;		; + Hidden Sectors
  2789                              <1> 	; eax = physical sector number
  2790                              <1> 	
  2791                              <1> 	; 27/11/2021
  2792 0000518A A1[446F0000]        <1> 	mov	eax, [free_map_sector] ; physical sector number
  2793                              <1> 	
  2794 0000518F E8ED0D0000          <1> 	call	wslot
  2795                              <1> 	; ebx = buffer data address (write operation bit is set)
  2796                              <1> 	; eax = physical sector number
  2797                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2798                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2799                              <1> 
  2800                              <1> 	; 27/11/2021
  2801                              <1> 	;mov	[free_map_buffer], ebx ; save free map buffer address
  2802                              <1> 
  2803 00005194 E8040E0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2804                              <1> 		      ; (at the beginning/head of the buffer chain)
  2805                              <1> 
  2806                              <1> 	; if we are here, buffer has been written to disk successfully 
  2807                              <1> 	; (otherwise cpu would jump to 'error' address)
  2808                              <1> 
  2809                              <1> 	; set superblock modified flag
  2810 00005199 BA[986E0000]        <1> 	mov	edx, smod
  2811 0000519E BB[546F0000]        <1> 	mov	ebx, systm
  2812 000051A3 F605[856E0000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2813 000051AA 7406                <1> 	jz	short alloc_9  ; no, root device
  2814                              <1> 	; yes, mounted device
  2815 000051AC BB[5C710000]        <1> 	mov	ebx, mount
  2816                              <1> 	;mov	edx, mmod
  2817 000051B1 42                  <1> 	inc	edx ; edx = offset mmod
  2818                              <1> alloc_9: 
  2819 000051B2 FE02                <1> 	inc	byte [edx] ; superblock modified !
  2820                              <1> 	
  2821                              <1> 	; Allocating a new sector/block (for file) has been completed here.
  2822 000051B4 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2823 000051B7 40                  <1> 	inc	eax ; 0FFFFFFFFh -> 0 
  2824 000051B8 7405                <1> 	jz	short alloc_10 ; not valid (not set)
  2825 000051BA 48                  <1> 	dec	eax ; Free Blocks
  2826 000051BB 48                  <1> 	dec	eax ; Free Blocks = Free Blocks - 1
  2827 000051BC 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax
  2828                              <1> alloc_10:
  2829 000051BF E8900E0000          <1> 	call	get_system_time
  2830                              <1> 		; eax = current time (as unix epoch time)
  2831                              <1> 	; 30/07/2021
  2832 000051C4 89435C              <1> 	mov	[ebx+SB.ModifTime], eax
  2833                              <1> 
  2834 000051C7 8B433C              <1> 	mov	eax, [ebx+SB.FirstFreeBlk] ; allocated block address
  2835 000051CA FF433C              <1> 	inc	dword [ebx+SB.FirstFreeBlk] 
  2836                              <1> 				; +1, new value of first free block
  2837                              <1> 				; (new search will be started from here)
  2838                              <1> 				; ((it may not be free, no problem))
  2839                              <1> 
  2840                              <1> 	; put free map buffer address in ebx
  2841                              <1> 	; 27/11/2021
  2842                              <1> 	;mov	ebx, [free_map_buffer]
  2843                              <1> 
  2844 000051CD C3                  <1> 	retn	
  2845                              <1> 
  2846                              <1> 	; 09/01/2022
  2847                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2848                              <1> free:
  2849                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2850                              <1> 	; 05/11/2021
  2851                              <1> 	; 29/10/2021 - temporary (simplified code)
  2852                              <1> 	; 14/08/2021
  2853                              <1> 	; 12/06/2021
  2854                              <1> 	; 07/06/2020
  2855                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  2856                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2857                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2858                              <1> 	;
  2859                              <1> 	; calculates byte address and bit position for given block number
  2860                              <1> 	; then sets the corresponding bit in the free storage map
  2861                              <1> 	; 
  2862                              <1> 	; INPUTS ->
  2863                              <1> 	;    r1 - block number for a block structured device
  2864                              <1> 	;    cdev - current device 
  2865                              <1> 	; OUTPUTS ->
  2866                              <1> 	;    free storage map is updated
  2867                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2868                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2869                              <1> 	;
  2870                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2871                              <1>         ;  ((Modified registers: DX, CX))  
  2872                              <1> 
  2873                              <1> 	; 27/11/2021
  2874                              <1> 	; INPUT:
  2875                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2876                              <1> 	;	eax = disk block/sector number/address (logical)
  2877                              <1> 	; OUTPUT:
  2878                              <1> 	;	ebx = superblock buffer address
  2879                              <1> 	;
  2880                              <1> 	;    Note:	
  2881                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2882                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2883                              <1> 	;	modification flag will be set; but the superblock 
  2884                              <1> 	;	will not be written to it's disk in this 'free' procedure)
  2885                              <1> 	;
  2886                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp 
  2887                              <1> 
  2888                              <1> 	; 27/11/2021
  2889 000051CE BB[546F0000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2890 000051D3 F605[856E0000]01    <1> 	test	byte [cdev], 1
  2891 000051DA 7405                <1> 	jz	short free_1
  2892 000051DC BB[5C710000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2893                              <1> free_1: ; 1
  2894                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2895                              <1> 	;test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2896                              <1> 	;jz	short free_2 
  2897                              <1> 	; 'read only file system' error
  2898 000051E1 C705[186F0000]1E00- <1> 	mov	dword [u.error], ERR_READ_ONLY_FS
  2898 000051E9 0000                <1>
  2899 000051EB E9BCE9FFFF          <1> 	jmp	error
  2900                              <1> free_2:
  2901 000051F0 89C1                <1> 	mov	ecx, eax ; logical sector/block number
  2902 000051F2 A3[446F0000]        <1> 	mov	[free_map_sector], eax
  2903 000051F7 C1E903              <1> 	shr	ecx, 3	; convert to fbmap byte offset
  2904 000051FA C1E80C              <1> 	shr	eax, 12 ; convert to fbmap sector index 
  2905                              <1> 			; (1 fb sector for 4096 sectors)
  2906                              <1> 	;and	cl, ~3	; dword alignment (to backward)
  2907 000051FD 890D[3C6F0000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm
  2908                              <1> 	; 27/11/2021
  2909                              <1> 	; eax = fbm sector index
  2910 00005203 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2911                              <1> 			; free blocks map start sector address
  2912                              <1> 	; 09/01/2022
  2913 00005206 034304              <1> 	add	eax, [ebx+SB.BootSectAddr]
  2914                              <1> 			; + Hidden Sectors
  2915                              <1> 	; ebx = superblock address
  2916                              <1> 	; eax = physical sector number
  2917 00005209 E8130D0000          <1> 	call	dskrd
  2918                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2919                              <1> 	; eax = physical sector number
  2920                              <1> 	; ebx = buffer data address
  2921                              <1> 	; 27/11/2021
  2922 0000520E A3[406F0000]        <1> 	mov	[free_map_index], eax  ; save physical sector address
  2923 00005213 8B15[3C6F0000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2924                              <1> 	;
  2925 00005219 29C0                <1> 	sub	eax, eax
  2926 0000521B A0[446F0000]        <1> 	mov	al, [free_map_sector] ; logical sector number
  2927 00005220 2407                <1> 	and	al, 7
  2928                              <1> 
  2929                              <1> 	; al = bit offset in fbm allocation byte
  2930                              <1> 	; edx = buffer address (start+offset)
  2931                              <1> 	; [free_map_offset] = byte position on fbm
  2932                              <1> 	; 27/11/2021
  2933 00005222 0FAB02              <1> 	bts	[edx], eax  ; copy value of bit position in eax to cf
  2934                              <1> 			    ; then set same bit position at [edx]
  2935 00005225 7305                <1> 	jnc	short free_3 ; it was allocated sector
  2936                              <1> 
  2937                              <1> 	; already free sector !? 
  2938                              <1> 	; (nonsence or defective fs)
  2939                              <1> 
  2940 00005227 30C0                <1> 	xor	al, al ; 0  ; eax = 0
  2941 00005229 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2942                              <1> 	;mov	[ebx+SB.FreeBlocks], eax 
  2943                              <1> 		; invalidate free blocks count
  2944 0000522A EB18                <1> 	jmp	short free_5
  2945                              <1> free_3:
  2946                              <1> 	; 27/11/2021
  2947 0000522C 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2948 0000522F 40                  <1> 	inc	eax
  2949 00005230 7401                <1> 	jz	short free_4 ; 0FFFFFFFFh -> 0 (invalid!)
  2950 00005232 48                  <1> 	dec	eax  ; 0 -> 0FFFFFFFFh (invalid!)
  2951                              <1> free_4: 
  2952 00005233 50                  <1> 	push	eax ; * ; number of free blocks 
  2953                              <1> 	;mov	eax, [free_map_index] ; fbm sector index
  2954                              <1> 	;add	eax, [ebx+SB.FreeMapAddr] 
  2955                              <1> 			; free blocks map start sector address
  2956                              <1> 	;add	eax, [ebx+SB.BootSectAddr]
  2957                              <1> 	;		; + Hidden Sectors
  2958 00005234 A1[406F0000]        <1> 	mov	eax, [free_map_index] ; restore physical sector address
  2959                              <1> 	; eax = physical sector number
  2960 00005239 E8430D0000          <1> 	call	wslot
  2961                              <1> 	; ebx = buffer data address (write operation bit is set)
  2962                              <1> 	; eax = physical sector number
  2963                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2964                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2965                              <1> 
  2966 0000523E E85A0D0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2967                              <1> 		      ; (at the beginning/head of the buffer chain)
  2968                              <1> 
  2969                              <1> 	; if we are here, buffer has been written to disk successfully 
  2970                              <1> 	; (otherwise cpu would jump to 'error' address)
  2971 00005243 58                  <1> 	pop	eax ; *  ; number of free blocks 
  2972                              <1> free_5:
  2973                              <1> 	; eax = number of free blocks 
  2974                              <1> 	;
  2975                              <1> 	; set superblock modified flag
  2976 00005244 BA[986E0000]        <1> 	mov	edx, smod
  2977 00005249 BB[546F0000]        <1> 	mov	ebx, systm
  2978 0000524E F605[856E0000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2979 00005255 7406                <1> 	jz	short free_6 ; no, root device
  2980                              <1> 	; yes, mounted device
  2981 00005257 BB[5C710000]        <1> 	mov	ebx, mount
  2982                              <1> 	;mov	edx, mmod
  2983 0000525C 42                  <1> 	inc	edx ; edx = offset mmod
  2984                              <1> free_6: 
  2985 0000525D 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax 
  2986                              <1> 
  2987 00005260 A1[446F0000]        <1> 	mov	eax, [free_map_sector] ; logical sector number
  2988 00005265 3B433C              <1> 	cmp	eax, [ebx+SB.FirstFreeBlk]
  2989 00005268 7303                <1> 	jnb	short free_7
  2990 0000526A 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2991                              <1> free_7:
  2992 0000526D FE02                <1> 	inc	byte [edx] ; superblock modified !
  2993 0000526F C3                  <1> 	retn
  2994                              <1> 	
  2995                              <1> iget:
  2996                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2997                              <1> 	; 30/11/2021
  2998                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2999                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3000                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  3001                              <1> 	;
  3002                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  3003                              <1> 	;
  3004                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  3005                              <1> 	; 
  3006                              <1> 	; INPUTS ->
  3007                              <1> 	;    ii - current i-number, rootdir
  3008                              <1> 	;    cdev - new i-node device
  3009                              <1> 	;    idev - current i-node device
  3010                              <1> 	;    imod - current i-node modified flag
  3011                              <1> 	;    mnti - cross device file i-number
  3012                              <1> 	;    r1 - i-numbe rof new i-node
  3013                              <1> 	;    mntd - mountable device number		
  3014                              <1> 	; 	 
  3015                              <1> 	; OUTPUTS ->
  3016                              <1> 	;    cdev, idev, imod, ii, r1
  3017                              <1> 	;
  3018                              <1> 	; ((AX = R1)) input/output
  3019                              <1> 	;
  3020                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3021                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3022                              <1> 
  3023                              <1> 	; 22/11/2021
  3024                              <1> 	;;mov	dl, [cdev] ; 18/07/2013
  3025                              <1> 	;;mov	dh, [idev] ; 07/08/2013
  3026                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3027                              <1> 	;mov	dh, [cdev]
  3028                              <1> 	;mov	dl, [idev]
  3029 00005270 668B15[846E0000]    <1> 	mov	dx, [idev] ; [idev] in dl, [cdev] in dh
  3030                              <1> 	;
  3031                              <1> 	; 22/11/2021
  3032 00005277 25FFFF0000          <1> 	and	eax, 0FFFFh
  3033 0000527C 3B05[806E0000]      <1> 	cmp 	eax, [ii]
  3034                              <1> 		; cmp r1,ii / r1 = i-number of current file
  3035 00005282 7504                <1> 	jne 	short iget_1
  3036                              <1> 		; bne 1f
  3037 00005284 38F2                <1> 	cmp	dl, dh
  3038                              <1> 		; cmp idev,cdev
  3039                              <1> 			  ; / is device number of i-node = current device
  3040 00005286 746C                <1>         je	short iget_5
  3041                              <1> 	;	; beq 2f
  3042                              <1> 	; 14/08/2021
  3043                              <1> iget_1: ; 1:
  3044 00005288 30DB                <1> 	xor	bl, bl
  3045 0000528A 381D[966E0000]      <1> 	cmp	[imod], bl ; 0	
  3046                              <1> 		; tstb imod / has i-node of current file
  3047                              <1> 			  ; / been modified i.e., imod set
  3048 00005290 7628                <1> 	jna	short iget_2
  3049                              <1> 		; beq 1f
  3050 00005292 881D[966E0000]      <1> 	mov	[imod], bl ; 0
  3051                              <1> 		;  clrb	imod / if it has, 
  3052                              <1> 			   ; / we must write the new i-node out on disk
  3053                              <1> 	; 22/11/2021 (32 bit push-pop)
  3054 00005298 50                  <1> 	push	eax ; *
  3055                              <1> 		; mov r1,-(sp)
  3056 00005299 52                  <1> 	push	edx ; **
  3057                              <1> 		; mov cdev,-(sp)
  3058 0000529A A1[806E0000]        <1> 	mov	eax, [ii]
  3059                              <1> 		; mov ii,r1
  3060                              <1> 	;mov	dh, [idev]
  3061                              <1> 	;mov	[cdev], dh
  3062                              <1> 	; 09/01/2022
  3063 0000529F 8815[856E0000]      <1> 	mov	[cdev], dl  ; dl = [idev]
  3064                              <1> 		; mov idev,cdev
  3065 000052A5 FEC3                <1> 	inc	bl ; 1
  3066                              <1> 	; 31/07/2013
  3067 000052A7 881D[386F0000]      <1> 	mov     [rw], bl ; 1 == write 
  3068                              <1> 	;;28/07/2013 rw -> u.rw
  3069                              <1>         ;;mov   [u.rw], bl ; 1 == write
  3070 000052AD E843000000          <1> 	call	icalc
  3071                              <1> 		; jsr r0,icalc; 1
  3072 000052B2 5A                  <1> 	pop	edx ; **
  3073 000052B3 8835[856E0000]      <1> 	mov	[cdev], dh ; 22/11/2021
  3074                              <1> 		; mov (sp)+,cdev
  3075 000052B9 58                  <1> 	pop	eax ; *
  3076                              <1> 		; mov (sp)+,r1
  3077                              <1> iget_2: ; 1:
  3078                              <1> 	;and	ax, ax
  3079 000052BA 21C0                <1> 	and	eax, eax ; 22/11/2021 (32 bit inode number)
  3080                              <1> 		; tst r1 / is new i-number non zero
  3081 000052BC 7431                <1> 	jz	short iget_4 ; 2f
  3082                              <1> 		; beq 2f / branch if r1=0
  3083                              <1> 
  3084                              <1> 	;mov 	dh, [cdev]
  3085 000052BE 08F6                <1> 	or	dh, dh ; 22/11/2021
  3086                              <1> 		; tst cdev / is the current device number non zero
  3087                              <1> 			 ; / (i.e., device =/ drum)
  3088 000052C0 7515                <1> 	jnz	short iget_3 ;  1f
  3089                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  3090                              <1> 	; 22/11/2021
  3091 000052C2 3B05[906E0000]      <1> 	cmp	eax, [mnti]
  3092                              <1> 	;cmp	ax, [mnti]			
  3093                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  3094                              <1> 			    ; / file (root directory of mounted device)
  3095 000052C8 750D                <1> 	jne	short iget_3 ; 1f
  3096                              <1> 		; bne 1f
  3097                              <1>         ;mov    bl, [mntd]
  3098 000052CA FEC6                <1> 	inc	dh ; mov dh, 1 ; 22/11/2021
  3099 000052CC 8835[856E0000]      <1>         mov	[cdev], dh ; 22/11/2021
  3100                              <1> 		; mov mntd,cdev / make mounted device the current device
  3101                              <1> 	; 22/11/2021
  3102 000052D2 A1[8C6E0000]        <1> 	mov	eax, [rootdir] ; rootdir = 1 (for runix v2 file system)
  3103                              <1> 	;mov	ax, [rootdir]
  3104                              <1> 		; mov rootdir,r1
  3105                              <1> iget_3: ; 1:
  3106                              <1> 	; 22/11/2021
  3107 000052D7 A3[806E0000]        <1> 	mov	[ii], eax ; 32 bit inode number
  3108                              <1> 	;mov	[ii], ax
  3109                              <1> 		; mov r1,ii
  3110                              <1> 	; 30/11/2021
  3111 000052DC 8835[846E0000]      <1> 	mov	[idev], dh ; cdev 
  3112                              <1> 	;mov	[idev], dl ; cdev
  3113                              <1> 		; mov cdev,idev
  3114 000052E2 30DB                <1> 	xor	bl, bl
  3115                              <1>         ; 31/07/2013
  3116 000052E4 881D[386F0000]      <1> 	mov     [rw], bl ; 0 == read 
  3117                              <1> 	;;28/07/2013 rw -> u.rw       
  3118                              <1>         ;;mov   [u.rw], bl ; 0 = read
  3119 000052EA E806000000          <1> 	call	icalc
  3120                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  3121                              <1> iget_4: ; 2:
  3122                              <1> 	; 22/11/2021
  3123 000052EF A1[806E0000]        <1> 	mov	eax, [ii]
  3124                              <1> 	;mov	ax, [ii]
  3125                              <1> 		; mov ii,r1
  3126                              <1> iget_5:
  3127 000052F4 C3                  <1> 	retn
  3128                              <1> 		; rts r0
  3129                              <1> 
  3130                              <1> icalc:
  3131                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3132                              <1> 	; 28/11/2021
  3133                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 
  3134                              <1> 	; 02/07/2015
  3135                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3136                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3137                              <1> 	;
  3138                              <1> 	; calculate physical block number from i-number then
  3139                              <1> 	; read or write that block
  3140                              <1> 	;
  3141                              <1> 	; 'icalc' is called from 'iget'
  3142                              <1> 	;
  3143                              <1> 	; for original unix v1:
  3144                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  3145                              <1>        	; / (i+31.) mod 16. bytes from its start
  3146                              <1> 	;
  3147                              <1> 	; for retro unix 8086 v1:
  3148                              <1> 	;  i-node is located in block (i+47)/16 and
  3149                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  3150                              <1> 	;
  3151                              <1> 	; INPUTS ->
  3152                              <1> 	;    r1 - i-number of i-node
  3153                              <1> 	; 	 
  3154                              <1> 	; OUTPUTS ->
  3155                              <1> 	;    inode r/w
  3156                              <1> 	;
  3157                              <1> 	; ((AX = R1)) input
  3158                              <1> 	;
  3159                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3160                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  3161                              <1> 	;
  3162                              <1> 
  3163                              <1> 	; 28/11/2021
  3164                              <1> 	;cmp	byte [idev], 0 ; [cdev] = [idev]
  3165 000052F5 803D[856E0000]00    <1> 	cmp	byte [cdev], 0
  3166 000052FC 7607                <1> 	jna	short icalc_0r
  3167 000052FE BD[5C710000]        <1> 	mov	ebp, mount  ; mounted file system's superblock 
  3168 00005303 EB05                <1> 	jmp	short icalc_0m
  3169                              <1> icalc_0r:
  3170                              <1> 	; 28/11/2021
  3171 00005305 BD[546F0000]        <1> 	mov	ebp, systm  ; root file system's superblock 
  3172                              <1> icalc_0m:
  3173                              <1> 	; 22/11/2021
  3174                              <1> 	;mov	edx, eax
  3175 0000530A 8B15[806E0000]      <1> 	mov	edx, [ii] ; 32 bit inode number
  3176 00005310 8B4528              <1> 	mov	eax, [ebp+SB.InodeTblAddr] ; inode table base address
  3177                              <1> 	;
  3178 00005313 4A                  <1> 	dec	edx ; 0 based inode number 
  3179                              <1> 		    ; (inode index in inode table)
  3180 00005314 52                  <1> 	push	edx ; *
  3181 00005315 C1EA03              <1> 	shr	edx, 3
  3182 00005318 7402                <1> 	jz	short icalc_0t ; 0 for inodes 1 to 8
  3183 0000531A 01D0                <1> 	add	eax, edx
  3184                              <1> icalc_0t:
  3185                              <1> 	; 09/01/2022
  3186                              <1> 	; eax = locical block/sector number 
  3187 0000531C 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  3188                              <1> 	; eax = physical block/sector number 
  3189 0000531F E8FD0B0000          <1> 	call	dskrd
  3190                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  3191                              <1> 	; 31/07/2013
  3192 00005324 803D[386F0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  3193                              <1> 	;; 28/07/2013 rw -> u.rw
  3194                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  3195                              <1> 		; tst (r0)
  3196 0000532B 7605                <1> 	jna	short icalc_1
  3197                              <1> 		; beq 1f / branch to wslot when argument
  3198                              <1> 		       ; / in icalc call = 1
  3199                              <1> 	; eAX = r1 = block number
  3200 0000532D E84F0C0000          <1> 	call	wslot
  3201                              <1> 		; jsr r0,wslot / set up data buffer for write
  3202                              <1> 			     ; / (will be same buffer as dskrd got)
  3203                              <1> 	; EBX = r5 points to first word in data area for this block
  3204                              <1> icalc_1: ; 1:
  3205 00005332 5A                  <1> 	pop	edx ; *
  3206                              <1> 	; 22/11/2021
  3207 00005333 83E207              <1> 	and 	edx, 07h ; 8 inodes per inode table sector
  3208 00005336 C1E206              <1> 	shl 	edx, 6 ; * 64 (inode size)
  3209                              <1> 	; edx = 64 * (mod(inodenumber-1)/8)
  3210 00005339 89DE                <1> 	mov	esi, ebx  ; ebx points to 1st word of the buffer
  3211 0000533B 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  3212                              <1>           	; eSI (r5) points to first word in i-node i.	
  3213                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  3214                              <1> 			     ; / 32.*(i+31.)mod16
  3215                              <1> 		; mov $5,lsh / for i-node i.
  3216                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  3217 0000533D BF[406B0000]        <1> 	mov	edi, inode
  3218                              <1> 		; mov $inode,r1 / inode is address of first word 
  3219                              <1> 			      ; / of current i-node
  3220                              <1> 	;mov 	ecx, 8 ; 02/07/2015 (32 bit modification)
  3221                              <1> 	;	; mov $16.,r3
  3222                              <1> 	; 28/11/2021
  3223 00005342 29C9                <1> 	sub	ecx, ecx
  3224 00005344 B110                <1> 	mov	cl, 16 ; Retro UNIX 386 v2 inode size = 64 bytes
  3225                              <1> 	; 31/07/2013
  3226 00005346 382D[386F0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3227                              <1>        ;;28/07/2013 rw -> u.rw                 
  3228                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3229                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  3230 0000534C 7609                <1> 	jna	short icalc_3
  3231                              <1> 		; beq 2f / r0 now contains proper return address 
  3232                              <1> 		       ; / for rts r0
  3233                              <1> icalc_2: ; 1:
  3234 0000534E 87F7                <1> 	xchg 	esi, edi
  3235                              <1> 	; overwrite old i-node (in buffer to be written)
  3236 00005350 F3A5                <1> 	rep 	movsd
  3237                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  3238                              <1> 		; dec r3
  3239                              <1> 		; bgt 1b
  3240                              <1> 	;call	dskwr
  3241                              <1> 	;	; jsr r0,dskwr / write inode out on device
  3242                              <1> 	;retn
  3243                              <1> 	;	; rts r0
  3244                              <1> 	; 28/11/2021
  3245 00005352 E9460C0000          <1> 	jmp	dskwr
  3246                              <1> icalc_3: ; 2:
  3247                              <1> 	; copy new i-node into inode area of (core) memory
  3248 00005357 F3A5                <1> 	rep 	movsd
  3249                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  3250                              <1> 		                ; / "inode" area of core
  3251                              <1> 		; dec r3
  3252                              <1> 		; bgt 2b
  3253 00005359 C3                  <1> 	retn
  3254                              <1> 		; rts r0
  3255                              <1> 
  3256                              <1> access:
  3257                              <1> 	; 25/12/2021
  3258                              <1> 	; 19/12/2021
  3259                              <1> 	; 28/11/2021
  3260                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3261                              <1> 	; 31/10/2021 - temporary (simplified code)
  3262                              <1> 	; 14/06/2021
  3263                              <1> 	; 02/05/2021
  3264                              <1> 	; 27/03/2021
  3265                              <1> 	; 26/03/2021
  3266                              <1> 	; 25/03/2021
  3267                              <1> 	; 23/03/2021 (Retro UNIX 386 v2 - Beginning)
  3268                              <1> 	;	((ref: unix v7 source - fio.c))
  3269                              <1> 	; ref: INODE STRUCTURE of Retro UNIX v2 file system
  3270                              <1> 	;	07/02/2020, 'RETRO UNIX v2 Inodes.pdf'
  3271                              <1> 	;	 
  3272                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3273                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3274                              <1> 	;
  3275                              <1> 	; check whether user is owner of file or user has read or write
  3276                              <1> 	; permission (based on i.flgs).
  3277                              <1> 	;
  3278                              <1> 	; INPUTS ->
  3279                              <1> 	;    r1 - i-number of file
  3280                              <1> 	;    u.uid
  3281                              <1> 	; arg0 -> (owner flag mask)	 		
  3282                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  3283                              <1> 	; OUTPUTS ->
  3284                              <1> 	;    inode (or jump to error)
  3285                              <1> 	;
  3286                              <1> 	; ((AX = R1)) input/output
  3287                              <1> 	;
  3288                              <1> 	;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))
  3289                              <1> 
  3290                              <1> 	; 26/03/2021
  3291                              <1> 	; INPUT:
  3292                              <1> 	;	eax = inode number (ax)
  3293                              <1> 	;	 dx = mode (IEXEC, IREAD or IWRITE) 
  3294                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3295                              <1> 	;	
  3296                              <1> 	; OUTPUT:
  3297                              <1> 	;	inode (or jump to error)
  3298                              <1> 	;	eax (ax) = [ii] = inode number
  3299                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3300                              <1> 	;
  3301                              <1> 	; Modified registers: (eax), ebx, ecx, edx, esi, edi, ebp
  3302                              <1> 	;
  3303                              <1> 	; IREAD	 equ 100h ; read permission flag, owner
  3304                              <1> 	; IWRITE equ 80h  ; write permission flag, owner
  3305                              <1> 	; IEXEC	 equ 40h  ; execute permission flag, owner	 
  3306                              <1> 		
  3307                              <1> 	; 23/03/2021
  3308 0000535A 52                  <1> 	push	edx ; save flag (DX)
  3309                              <1> 	;push	dx  ; save flag (DL)
  3310 0000535B E810FFFFFF          <1> 	call	iget
  3311                              <1> 		; jsr r0,iget / read in i-node for current directory
  3312                              <1> 			    ; / (i-number passed in r1)
  3313                              <1> 	;;mov	cl, [i.flgs]
  3314                              <1> 	;;	; mov i.flgs,r2
  3315                              <1> 	; 23/03/2021
  3316                              <1> 	;mov	cx, [i.iflgs]	
  3317                              <1> 
  3318                              <1> 	;;pop	dx  ; restore flag (DL)
  3319                              <1> 	; 23/03/2021
  3320 00005360 5A                  <1> 	pop	edx ; restore flag (DX)
  3321                              <1> 
  3322                              <1> 	; 28/11/2021 (iget will not return here if there is an error)
  3323                              <1> 	; 31/10/2021
  3324                              <1> 	;jc	short access_5
  3325                              <1> 
  3326                              <1> 	; 31/10/2021
  3327                              <1> 	; Note: If eax input is same with [mnti], 'iget' will change
  3328                              <1> 	; [cdev] to 1 and eax will be 1 (root dir of mounted fs) 
  3329                              <1> 
  3330                              <1> 	; 27/03/2021
  3331                              <1> 	; 23/03/2021
  3332                              <1> 	; (check if it is write permission flag)
  3333 00005361 6681FA8000          <1> 	cmp	dx, 80h ; IWRITE
  3334 00005366 775E                <1> 	ja	short access_r	; IREAD = 100h (owner)
  3335 00005368 722B                <1> 	jb	short access_x	; IEXEC = 40h (owner)
  3336                              <1> 	; IWRITE (80h)
  3337                              <1> access_w:
  3338                              <1> 	; 23/03/2021
  3339                              <1> 	; ((ref: Retro UNIX 386 v2, 'ux.s', 'ldrv' structure))
  3340                              <1> 	;mov	bl, [idev]
  3341                              <1> 	;call	getfs
  3342                              <1>  	;movzx	ebx, byte [idev]  ; logical drive number
  3343                              <1> 	;shl	bx, 6 ; * 64	  ; of current inode	
  3344                              <1> 	;add	ebx, ldrvtable	
  3345                              <1> 	;;test	byte [ebx+ldrv.pflags], 01h ; read only fs flag
  3346                              <1> 	;;jz	short access_0
  3347                              <1> 	;; 14/06/2021
  3348                              <1> 	; 14/06/2021
  3349                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3350                              <1> 	;mov	edi, [ebx+ldrv.superblk]
  3351                              <1> 	;test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3352                              <1> 	;jz	short access_0
  3353                              <1> 	; 31/10/2021
  3354 0000536A 803D[856E0000]01    <1> 	cmp	byte [cdev], 1
  3355 00005371 7207                <1> 	jb	short access_7 ; [cdev] = 0
  3356                              <1> 	; [cdev] = 1
  3357                              <1> 	; 28/11/2021
  3358 00005373 BF[5C710000]        <1> 	mov	edi, mount ; mounted file system's superblock buffer
  3359 00005378 EB05                <1> 	jmp	short access_8
  3360                              <1> access_7:
  3361                              <1> 	; 28/11/2021
  3362 0000537A BF[546F0000]        <1> 	mov	edi, systm ; root file system's superblock buffer
  3363                              <1> access_8:
  3364 0000537F F6476A01            <1> 	test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3365 00005383 7441                <1> 	jz	short access_0
  3366                              <1> 
  3367                              <1> 	; 23/03/2021
  3368                              <1> 	;mov	dword [u.error], ERR_READ_ONLY_FS
  3369                              <1> 	;		; 'read only file system !' error
  3370                              <1> 	;jmp	error
  3371                              <1> 
  3372                              <1> 	; 19/12/2021
  3373 00005385 F605[416B0000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  3374 0000538C 7438                <1> 	jz	short access_0  ; no, device file
  3375                              <1> 
  3376                              <1> 	; 31/10/2021
  3377 0000538E B81E000000          <1> 	mov	eax, ERR_READ_ONLY_FS
  3378                              <1> 			; 'read only file system !' error
  3379                              <1> 	; 27/03/2021
  3380 00005393 EB27                <1> 	jmp	short access_5
  3381                              <1> 
  3382                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3383                              <1> 
  3384                              <1> 	;mov	dh, [u.uid]
  3385                              <1> 	;cmp	dh, [i.uid]
  3386                              <1> 	;	; cmpb i.uid,u.uid / is user same as owner of file
  3387                              <1> 	;jne	short access_1
  3388                              <1> 		; bne 1f / no, then branch
  3389                              <1> access_x:
  3390                              <1> 	; IEXEC (40h)
  3391                              <1> 	; 27/03/2021
  3392 00005395 668B1D[406B0000]    <1> 	mov	bx, [i.flgs]
  3393 0000539C F6C780              <1> 	test	bh, 80h ; regular file ?
  3394 0000539F 7416                <1> 	jz	short access_4 ; not executable file !
  3395 000053A1 F6C740              <1> 	test	bh, 40h	; directory ?
  3396 000053A4 7511                <1> 	jnz	short access_4 ; not executable file !
  3397 000053A6 668B0D[F66E0000]    <1> 	mov	cx, [u.uid]
  3398 000053AD 6609C9              <1> 	or	cx, cx
  3399 000053B0 7520                <1> 	jnz	short access_3 ; (restricted user)
  3400                              <1> 	; (super user)
  3401                              <1> 	;test	[i.flgs], dl ; execute permission for owner
  3402                              <1> 	;test	byte [i.flgs], 49h ; for owner, group, others
  3403 000053B2 F6C349              <1> 	test	bl, 49h ; exec perm for owner, group, others
  3404 000053B5 7557                <1> 	jnz	short access_2
  3405                              <1> access_4:
  3406                              <1> 	; 31/10/2021
  3407 000053B7 B816000000          <1> 	mov	eax, ERR_NOT_EXECUTABLE
  3408                              <1> 			; 'not executable file !' error
  3409                              <1> 	; 26/03/2021
  3410                              <1> ;;sysexec_not_exf:
  3411                              <1> ;	mov	dword [u.error], ERR_NOT_EXECUTABLE
  3412                              <1> ;			; 'not executable file !' error
  3413                              <1> ;access_5:
  3414                              <1> ;	jmp	error
  3415                              <1> 	
  3416                              <1> 	; 31/10/2021
  3417                              <1> access_5:
  3418 000053BC A3[186F0000]        <1> 	mov	[u.error], eax
  3419 000053C1 E9E6E7FFFF          <1> 	jmp	error
  3420                              <1> 
  3421                              <1> access_r:
  3422                              <1> 	; 27/03/2021
  3423                              <1> access_0:
  3424                              <1> 	; 23/03/2021
  3425 000053C6 668B0D[F66E0000]    <1> 	mov	cx, [u.uid]
  3426 000053CD 6609C9              <1> 	or	cx, cx ; 0 ; root ?
  3427                              <1> 	;jz	short access_2 ; yes
  3428                              <1> 	; 25/12/2021
  3429 000053D0 742C                <1> 	jz	short access_1 ; yes
  3430                              <1> access_3:
  3431                              <1> 	; owner ?
  3432 000053D2 8A1D[466B0000]      <1> 	mov	bl, [i.gid]
  3433 000053D8 663B0D[446B0000]    <1> 	cmp	cx, [i.uid]
  3434                              <1> 	;je	short access_1
  3435                              <1> 	; 02/05/2021
  3436 000053DF 750E                <1> 	jne	short access_6
  3437                              <1> 	; check owner's group number/ID
  3438 000053E1 3A1D[FA6E0000]      <1> 	cmp	bl, [u.gid] ; same group number/ID ?
  3439 000053E7 7415                <1> 	je	short access_1 ; yes, owner
  3440                              <1> 	; one of others
  3441 000053E9 66C1EA06            <1> 	shr	dx, 6
  3442 000053ED EB0F                <1> 	jmp	short access_1 ; others
  3443                              <1> access_6:
  3444                              <1> 	;shr	cl, 2
  3445                              <1> 	;	; asrb r2 / shift owner read write bits into non owner
  3446                              <1> 	;	;       ; / read/write bits
  3447                              <1> 	;	; asrb r2
  3448                              <1> 
  3449                              <1> 	; 23/03/2021
  3450                              <1> 	; same group ?
  3451 000053EF 66C1EA03            <1> 	shr	dx, 3
  3452                              <1> 	;mov	cl, [u.gid]
  3453                              <1> 	;cmp	cl, [i.gid]
  3454                              <1> 	;je	short access_1
  3455                              <1> 	; 02/05/2021
  3456 000053F3 3A1D[FA6E0000]      <1> 	cmp	bl, [u.gid]
  3457 000053F9 7403                <1> 	je	short access_1 ; same group, different owner
  3458                              <1> 
  3459                              <1> 	; others
  3460                              <1> 	;shr	dx, 3
  3461 000053FB C0EA03              <1> 	shr	dl, 3
  3462                              <1> 	;jmp	short access_1	
  3463                              <1> 
  3464                              <1> ;access_1: ; 1:
  3465                              <1> 	;and	cl, dl
  3466                              <1> 	;	; bit r2,(r0)+ / test read-write flags against argument
  3467                              <1> 	;		     ; / in access call
  3468                              <1> 	;jnz	short access_2
  3469                              <1> 	;	; bne 1f
  3470                              <1> 	
  3471                              <1> 	;or	dh, dh	; super user (root) ?
  3472                              <1> 	;	; tstb u.uid
  3473                              <1> 	;jz	short access_2 ; yes, super user
  3474                              <1> 	;;jnz	error
  3475                              <1> 	;	; beq 1f
  3476                              <1> 	;	; jmp error
  3477                              <1> 	
  3478                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3479                              <1> 	;		; 'permission denied !' error
  3480                              <1> 	;jmp	error
  3481                              <1> 
  3482                              <1> access_1:
  3483                              <1> 	; 23/03/2021
  3484 000053FE 668515[406B0000]    <1> 	test	dx, [i.flgs]
  3485 00005405 7507                <1> 	jnz	short access_2
  3486                              <1> 
  3487                              <1> 	;; r/w permission error
  3488                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3489                              <1> 	;		; 'permission denied !' error
  3490                              <1> 	;;jmp	error
  3491                              <1> 
  3492                              <1> 	; 31/10/2021
  3493 00005407 B80B000000          <1> 	mov	eax, ERR_FILE_ACCESS 
  3494                              <1> 			; 'permission denied !' error
  3495                              <1> 	; 27/03/2021
  3496 0000540C EBAE                <1> 	jmp	short access_5
  3497                              <1> 
  3498                              <1> access_2: ; 1:
  3499                              <1> 	;; DL = flags
  3500                              <1> 	;retn
  3501                              <1> 	;	; rts r0
  3502                              <1> 	; 27/03/2021
  3503                              <1> 	; DX = flag (100h-20h-04h or 80h-10h-02h or 40h-08h-01h)
  3504 0000540E C3                  <1> 	retn
  3505                              <1> 
  3506                              <1> setimod:
  3507                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3508                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3509                              <1> 	;
  3510                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3511                              <1> 	; the inode has been modified. Also puts the time of modification
  3512                              <1> 	; into the inode.
  3513                              <1> 	;
  3514                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3515                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3516                              <1> 	;
  3517                              <1> 	
  3518                              <1> 	; push 	edx
  3519 0000540F 50                  <1> 	push	eax
  3520                              <1> 
  3521 00005410 C605[966E0000]01    <1> 	mov 	byte [imod], 1
  3522                              <1> 		; movb $1,imod / set current i-node modified bytes
  3523                              <1> 	; Erdogan Tan 14-7-2012
  3524 00005417 E8ADE2FFFF          <1> 	call 	epoch
  3525                              <1> 		 ; mov s.time,i.mtim 
  3526                              <1> 			    ; / put present time into file modified time
  3527                              <1> 		 ; mov s.time+2,i.mtim+2
  3528                              <1> 
  3529 0000541C A3[786B0000]        <1> 	mov 	[i.mtim], eax
  3530                              <1> 	
  3531                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3532                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3533 00005421 833D[7C6B0000]00    <1> 	cmp	dword [i.ctim], 0
  3534 00005428 7505                <1> 	jnz	short setimod_ok
  3535                              <1> 
  3536 0000542A A3[7C6B0000]        <1> 	mov 	[i.ctim], eax
  3537                              <1> 
  3538                              <1> setimod_ok: ; 31/07/2013
  3539 0000542F 58                  <1> 	pop	eax
  3540                              <1> 	;pop	edx
  3541                              <1> 	
  3542 00005430 C3                  <1> 	retn
  3543                              <1> 		; rts r0
  3544                              <1> 
  3545                              <1> ; 10/01/2022 - Retro UNIX 386 v1.2
  3546                              <1> %if 0
  3547                              <1> 	; Retro UNIX 386 v1.1 'itrunc' code
  3548                              <1> itrunc:
  3549                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3550                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  3551                              <1> 	;
  3552                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3553                              <1> 	;  to zero length.
  3554                              <1> 	;
  3555                              <1> 	; INPUTS ->
  3556                              <1> 	;    r1 - i-number of i-node
  3557                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  3558                              <1> 	;    i.flgs - large file flag		
  3559                              <1> 	;    i.size - size of file	
  3560                              <1> 	; 	 
  3561                              <1> 	; OUTPUTS ->
  3562                              <1> 	;    i.flgs - large file flag is cleared
  3563                              <1> 	;    i.size - set to 0	
  3564                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  3565                              <1> 	;    setimod - set to indicate i-node has been modified
  3566                              <1> 	;    r1 - i-number of i-node  					
  3567                              <1> 	;
  3568                              <1> 	; ((AX = R1)) input/output
  3569                              <1> 	;
  3570                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  3571                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3572                              <1> 
  3573                              <1> 	call	iget
  3574                              <1> 		; jsr r0,iget
  3575                              <1> 	mov	esi, i.dskp
  3576                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  3577                              <1> 	xor	eax, eax
  3578                              <1> itrunc_1: ; 1:
  3579                              <1> 	lodsw
  3580                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  3581                              <1> 	or 	ax, ax
  3582                              <1> 	jz	short itrunc_5
  3583                              <1> 		; beq 5f
  3584                              <1> 	push	esi
  3585                              <1> 		; mov r2,-(sp)
  3586                              <1> 	test    word [i.flgs], 1000h    
  3587                              <1> 		; bit $10000,i.flgs / test large file bit?
  3588                              <1> 	jz	short itrunc_4
  3589                              <1> 		; beq 4f / if clear, branch
  3590                              <1> 	push	eax
  3591                              <1> 		; mov r1,-(sp) / save block number of indirect block
  3592                              <1> 	call	dskrd
  3593                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  3594                              <1> 			     ; / pointed to by r5
  3595                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  3596                              <1> 	mov	ecx, 256
  3597                              <1> 		; mov $256.,r3 / move word count into r3
  3598                              <1> 	mov	esi, ebx
  3599                              <1> itrunc_2: ; 2:
  3600                              <1> 	lodsw
  3601                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  3602                              <1> 			     ; / physical block number
  3603                              <1> 	and	ax, ax
  3604                              <1> 	jz	short itrunc_3
  3605                              <1> 		; beq 3f / branch if zero
  3606                              <1> 	;push	ecx
  3607                              <1> 	push	cx
  3608                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3609                              <1> 	;push	esi
  3610                              <1> 		; mov r5,-(sp)
  3611                              <1> 	call	free
  3612                              <1> 		; jsr r0,free / free block in free storage map
  3613                              <1> 	;pop	esi
  3614                              <1> 		; mov(sp)+,r5
  3615                              <1> 	pop	cx
  3616                              <1> 	;pop	ecx
  3617                              <1> 		; mov (sp)+,r3
  3618                              <1> itrunc_3: ; 3:
  3619                              <1> 	loop	itrunc_2
  3620                              <1> 		; dec r3 / decrement word count
  3621                              <1> 		; bgt 2b / branch if positive
  3622                              <1> 	pop	eax
  3623                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3624                              <1> 			     ; / indirect block
  3625                              <1> 	; 01/08/2013
  3626                              <1>         and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3627                              <1> itrunc_4: ; 4:
  3628                              <1> 	call	free
  3629                              <1> 		; jsr r0,free / free indirect block
  3630                              <1> 	pop	esi
  3631                              <1> 		; mov (sp)+,r2
  3632                              <1> itrunc_5: ; 5:
  3633                              <1> 	cmp	esi, i.dskp+16
  3634                              <1> 		; cmp r2,$i.dskp+16.
  3635                              <1> 	jb	short itrunc_1	
  3636                              <1> 		; bne 1b / branch until all i.dskp entries check
  3637                              <1> 	; 01/08/2013
  3638                              <1> 	;and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3639                              <1> 		; bic $10000,i.flgs / clear large file bit
  3640                              <1> 	mov	edi, i.dskp
  3641                              <1> 	mov	cx, 8
  3642                              <1> 	xor 	ax, ax
  3643                              <1> 	mov	[i.size], ax ; 0
  3644                              <1> 		; clr i.size / zero file size
  3645                              <1> 	rep	stosw
  3646                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3647                              <1> 			   ; / zero block pointers
  3648                              <1> 	call	setimod
  3649                              <1> 		; jsr r0,setimod / set i-node modified flag
  3650                              <1> 	mov	ax, [ii]
  3651                              <1> 		; mov ii,r1
  3652                              <1> 	retn
  3653                              <1> 		; rts r0
  3654                              <1> 
  3655                              <1> 	; Retro UNIX 386 v1.1 'imap' code
  3656                              <1> imap:
  3657                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3658                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3659                              <1> 	;
  3660                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3661                              <1> 	; allocation bit for an i-node whose number in r1.
  3662                              <1> 	;
  3663                              <1> 	; INPUTS ->
  3664                              <1> 	;    r1 - contains an i-number
  3665                              <1> 	;    fsp - start of table containing open files
  3666                              <1> 	;
  3667                              <1> 	; OUTPUTS ->
  3668                              <1> 	;    r2 - byte address of byte with the allocation bit
  3669                              <1> 	;    mq - a mask to locate the bit position.	
  3670                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3671                              <1> 	;
  3672                              <1> 	; ((AX = R1)) input/output
  3673                              <1> 	; ((DL/DX = MQ)) output
  3674                              <1> 	; ((BX = R2)) output
  3675                              <1> 	;
  3676                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3677                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3678                              <1> 	;
  3679                              <1> 		; / get the byte that has the allocation bit for 
  3680                              <1> 		; / the i-number contained in r1
  3681                              <1> 	;mov	dx, 1
  3682                              <1> 	mov	dl, 1
  3683                              <1> 		; mov $1,mq / put 1 in the mq
  3684                              <1> 	movzx	ebx, ax
  3685                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3686                              <1>  		          ; / in the map we must find
  3687                              <1> 	sub	bx, 41
  3688                              <1> 		; sub $41.,r2 / r2 has i-41
  3689                              <1> 	mov	cl, bl
  3690                              <1> 		; mov r2,r3 / r3 has i-41
  3691                              <1> 	and	cl, 7
  3692                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3693                              <1> 			   ; / the bit position
  3694                              <1> 	jz	short imap1
  3695                              <1> 	;shl	dx, cl
  3696                              <1> 	shl	dl, cl
  3697                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3698                              <1> imap1:			   ; / to the left to mask the correct bit
  3699                              <1> 	shr	bx, 3
  3700                              <1> 		; asr r2
  3701                              <1> 		; asr r2
  3702                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3703                              <1> 		       ; / from the start of the map
  3704                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3705                              <1> 	mov	esi, systm
  3706                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3707                              <1> 				; / the super block for drum
  3708                              <1> 	;cmp	word [cdev], 0
  3709                              <1> 	cmp	byte [cdev], 0
  3710                              <1> 		; tst cdev / is the device the disk
  3711                              <1> 	jna	short imap2
  3712                              <1> 		; beq 1f / yes
  3713                              <1> 	add	esi, mount - systm
  3714                              <1> 		; add $mount-systm,r2 / for mounted device,
  3715                              <1> 			; / r2 points to 1st word of its super block
  3716                              <1> imap2: ; 1:
  3717                              <1> 	add	bx, [esi] ;; add free map size to si
  3718                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3719                              <1> 	add	bx, 4
  3720                              <1> 	add	ebx, esi
  3721                              <1>         	; add (sp)+,r2 / ?
  3722                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3723                              <1> 		      ;; (2 + free map size + 2)
  3724                              <1> 		; add $2,r2 / ?
  3725                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3726                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3727                              <1> 	retn
  3728                              <1> 		; rts r0
  3729                              <1> %endif
  3730                              <1> 
  3731                              <1> 	; Retro UNIX 386 v2.0 'itrunc' code
  3732                              <1> itrunc:
  3733                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  3734                              <1> 	; 07/06/2020
  3735                              <1> 	; 02/06/2020
  3736                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3737                              <1> 	;
  3738                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3739                              <1> 	;  to zero length.
  3740                              <1> 	; 07/06/2020
  3741                              <1> 	; 02/06/2020
  3742                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  3743                              <1> 	;
  3744                              <1> 	; 'itrunc' truncates a file whose i-number is given
  3745                              <1> 	; in ax to zero length.
  3746                              <1> 	;
  3747                              <1> 
  3748                              <1> 	; Reference: 
  3749                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  3750                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'itrunc' procedure
  3751                              <1> 
  3752                              <1> 	; * Free all the disk blocks associated
  3753                              <1> 	; * with the specified inode structure.
  3754                              <1> 	
  3755                              <1> 	; INPUT: 
  3756                              <1> 	;	ax = inode number
  3757                              <1> 	; OUTPUT: 
  3758                              <1> 	;	inode will be modified (file size = 0)
  3759                              <1> 
  3760                              <1> 	; (Modified registers: eax, edx, ecx, ebx, esi, edi, ebp) 
  3761                              <1> 
  3762                              <1> 	; 07/06/2020
  3763                              <1> 
  3764                              <1> 	; [cdev] = current logical drive number
  3765                              <1> 	;    eax = inode number (for [cdev])
  3766                              <1> 
  3767 00005431 E83AFEFFFF          <1> 	call 	iget
  3768                              <1> 	; 10/01/2022
  3769                              <1> 	;jc	short itrunc_0 ; error code in eax (al)
  3770                              <1> 
  3771                              <1> 	;    eax = inode number, [ii]
  3772                              <1> 	; [cdev] = current logical drive number (same with input)
  3773                              <1> 	; [idev] = logical drive number of current inode, [ii]
  3774                              <1> 	;   [ii] = current inode ([ii] = ax input, if ax was not zero)
  3775                              <1> 	; [imod] = 0		
  3776                              <1> 	; ([imodx] = 0)
  3777                              <1> 
  3778 00005436 F605[416B0000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file or directory	
  3779 0000543D 750F                <1> 	jnz	short itrunc_1
  3780                              <1> 
  3781                              <1> 	; 10/01/2022
  3782 0000543F C705[186F0000]FF00- <1> 	mov	dword [u.error], ERR_NOT_REGULAR ; 255 
  3782 00005447 0000                <1>
  3783                              <1> 			; 'not a regular file (or directory) !' error
  3784                              <1> itrunc_0:
  3785 00005449 E95EE7FFFF          <1> 	jmp	error
  3786                              <1> itrunc_1:
  3787 0000544E F605[416B0000]10    <1> 	test	byte [i.flgs+1], 10h ; large file (indirect blocks)
  3788 00005455 7525                <1> 	jnz	short itrunc_5 ; large file
  3789 00005457 BE[4C6B0000]        <1> 	mov	esi, i.dskp ; disk address pointer 0
  3790                              <1> itrunc_2:
  3791 0000545C AD                  <1> 	lodsd
  3792 0000545D 21C0                <1> 	and	eax, eax
  3793 0000545F 740C                <1> 	jz	short itrunc_3 ; empty ! (no more sectors/blocks)
  3794                              <1> 	; eax = block address to be released
  3795 00005461 56                  <1> 	push	esi ; * ; 10/01/2022
  3796 00005462 E867FDFFFF          <1> 	call	free
  3797                              <1> 	; modified registers: ebx, ecx, edx, esi, edi, ebp 
  3798                              <1> 	; 10/01/2022
  3799                              <1> 	;jc	short itrunc_0 ; error code in eax
  3800 00005467 5E                  <1> 	pop	esi ; * ; 10/01/2022
  3801 00005468 31C0                <1> 	xor	eax, eax ; 0
  3802 0000546A 8946FC              <1> 	mov	[esi-4], eax ; 0
  3803                              <1> itrunc_3:
  3804 0000546D 81FE[746B0000]      <1> 	cmp	esi, i.dskp+40
  3805 00005473 72E7                <1> 	jb	short itrunc_2 ; next disk address ptr
  3806                              <1> itrunc_4:
  3807 00005475 A3[486B0000]        <1> 	mov	[i.size], eax ; 0
  3808                              <1> 	;mov	[i.size_h], al ; 0
  3809                              <1> 	
  3810                              <1> 	; clear large file flag
  3811                              <1> 	;and     byte [i.flgs+1], 0EFh ; 11101111b ;  not 10h
  3812                              <1> 		
  3813                              <1> 	;call	setimod
  3814                              <1> 	;retn
  3815 0000547A EB93                <1> 	jmp	setimod
  3816                              <1> 
  3817                              <1> itrunc_5:
  3818                              <1> 	; free disk blocks by using triple indirect blocks at first
  3819 0000547C BE[706B0000]        <1> 	mov	esi, i.dskp+36
  3820 00005481 8B06                <1> 	mov	eax, [esi]
  3821 00005483 09C0                <1> 	or	eax, eax
  3822 00005485 740C                <1> 	jz	short itrunc_6
  3823                              <1> 
  3824 00005487 BA02000000          <1> 	mov	edx, 2 ; Triple indirect sign (level = 2)
  3825 0000548C E835000000          <1> 	call	tloop
  3826                              <1> 	; 10/01/2022
  3827                              <1> 	;jc	short itrunc_0
  3828                              <1> 		; eax = 0	
  3829 00005491 8906                <1> 	mov	[esi], eax ; 0
  3830                              <1> itrunc_6:
  3831                              <1> 	; free disk blocks by using double indirect blocks at second
  3832 00005493 BE[6C6B0000]        <1> 	mov	esi, i.dskp+32
  3833 00005498 8B06                <1> 	mov	eax, [esi]
  3834 0000549A 21C0                <1> 	and	eax, eax 
  3835 0000549C 740C                <1> 	jz	short itrunc_7
  3836                              <1> 
  3837 0000549E BA01000000          <1> 	mov	edx, 1 ; Double indirect sign (level = 1)
  3838 000054A3 E81E000000          <1> 	call	tloop
  3839                              <1> 	; 10/01/2022
  3840                              <1> 	;jc	short itrunc_0
  3841                              <1> 		; eax = 0	
  3842 000054A8 8906                <1> 	mov	[esi], eax ; 0
  3843                              <1> 	;esi = i.dskp+32
  3844                              <1> itrunc_7:
  3845                              <1> 	; free disk blocks by using single indirect blocks at third
  3846 000054AA 83EE04              <1> 	sub	esi, 4
  3847 000054AD 8B06                <1> 	mov	eax, [esi]
  3848 000054AF 09C0                <1> 	or	eax, eax
  3849 000054B1 7409                <1> 	jz	short itrunc_8
  3850                              <1> 
  3851 000054B3 29D2                <1> 	sub	edx, edx ; 0  ; Single indirect sign (level = 0)
  3852 000054B5 E80C000000          <1> 	call	tloop
  3853                              <1> 	; 10/01/2022
  3854                              <1> 	;jc	short itrunc_0
  3855                              <1> 		; eax = 0
  3856 000054BA 8906                <1> 	mov	[esi], eax ; 0
  3857                              <1> itrunc_8:
  3858 000054BC 81FE[4C6B0000]      <1> 	cmp	esi, i.dskp
  3859 000054C2 77E6                <1> 	ja	short itrunc_7
  3860 000054C4 EBAF                <1> 	jmp	short itrunc_4
  3861                              <1> 
  3862                              <1> tloop:
  3863                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  3864                              <1> 	; 07/06/2020
  3865                              <1> 	; 03/06/2020
  3866                              <1> 	; 02/06/2020
  3867                              <1> 	; 26/05/2020 - Retro UNIX 386 v2 by Erdogan Tan
  3868                              <1> 	; 
  3869                              <1> 	; * Free all the disk blocks associated
  3870                              <1> 	; * with the specified inode structure.
  3871                              <1> 
  3872                              <1> 	; Reference: 
  3873                              <1> 	;	Retro UNIX 386 v2 FS installation utility
  3874                              <1> 	; 17/01/2020 - 'UNIXHDCP.ASM', 'tloop' procedure
  3875                              <1> 
  3876                              <1> 	; INPUT: 
  3877                              <1> 	;	03/06/2020
  3878                              <1> 	;	eax = indirect block number/address (logical)
  3879                              <1> 	;	edx = level (in dl) 
  3880                              <1> 	;	(0 = indirect, 1 = double indr. 2 = triple indr.) 	
  3881                              <1> 	;
  3882                              <1> 	; OUTPUT: 
  3883                              <1> 	;	indirect blocks will be released
  3884                              <1> 	;
  3885                              <1> 	; Modified registers: eax, ebx, ecx, edx
  3886                              <1> 
  3887                              <1> 	; 03/06/2020
  3888                              <1> 
  3889 000054C6 57                  <1> 	push	edi ; *
  3890 000054C7 56                  <1> 	push	esi ; **
  3891                              <1> 
  3892 000054C8 50                  <1> 	push	eax ; ***
  3893                              <1> 
  3894 000054C9 52                  <1> 	push	edx ; **** level
  3895                              <1> 
  3896                              <1> 	; [ii] = current inode number
  3897                              <1> 	; [idev] = logical drive number of current inode, [ii]
  3898                              <1> 	; eax = logical sector/block number
  3899                              <1> 
  3900                              <1> 	; 10/01/2022
  3901                              <1> 	; convert to physical sector/block number/address
  3902 000054CA E884FAFFFF          <1> 	call	mget_2	
  3903                              <1> 
  3904 000054CF E84D0A0000          <1> 	call	dskrd ; read disk sector
  3905                              <1> 
  3906                              <1> 		;; ebx = buffer header address
  3907                              <1> 		;; eax = physical sector/block number 
  3908                              <1> 		;; [pdn] = phsysical drive (index) number
  3909                              <1> 		
  3910                              <1> 		;; Modified registers: eax, edx, ecx, esi, edi
  3911                              <1> 		;; If cf = 1 --> eax = error code (al)
  3912                              <1> 
  3913                              <1> 	; 10/01/2022
  3914                              <1> 	; Return from 'dskrd': (Retro UNIX 386 v1.2)
  3915                              <1> 	; 	eax = physical block/sector number
  3916                              <1> 	; 	ebx = buffer data address
  3917                              <1>  	; Modified registers: edx, ecx, ebx, esi, edi, ebp
  3918                              <1>  
  3919 000054D4 5A                  <1> 	pop	edx ; **** ; level in dl
  3920                              <1> 	; 10/01/2022
  3921                              <1> 	;jc	short tloop_5
  3922                              <1> 
  3923                              <1> 	;mov	esi, [ebx+bufhdr.address] ; buffer address
  3924                              <1> 	; 10/01/2022
  3925 000054D5 89DE                <1> 	mov	esi, ebx ; buffer data address	
  3926                              <1> 
  3927                              <1> 	; 07/06/2020
  3928 000054D7 B980000000          <1> 	mov	ecx, 512/4 ; 128 dwords	
  3929                              <1> 
  3930 000054DC 80FA01              <1> 	cmp	dl, 1 ; -
  3931 000054DF 722A                <1> 	jb	short tloop_7
  3932 000054E1 7407                <1> 	je	short tloop_1
  3933 000054E3 BF[5C750000]        <1> 	mov	edi, trpi_buf ; triple indirect buffer address
  3934 000054E8 EB05                <1> 	jmp	short tloop_2
  3935                              <1> tloop_1:
  3936 000054EA BF[5C730000]        <1> 	mov	edi, dbli_buf ; double indirect buffer address
  3937                              <1> tloop_2:
  3938                              <1> 	; copy disk r/w buffer content to indirect block buffer
  3939                              <1> 	;mov	ecx, 512/4 ; 128 dwords	
  3940 000054EF F3A5                <1> 	rep	movsd
  3941                              <1> 
  3942 000054F1 FECA                <1> 	dec	dl ; -
  3943                              <1> 		   ; next indirect block level, 2 -> 1, 1 -> 0
  3944 000054F3 89FE                <1> 	mov	esi, edi  ; (dbli, trpi) indirect buffer + 512
  3945 000054F5 B180                <1> 	mov	cl, 128 ; 128 dwords
  3946                              <1> tloop_3:
  3947 000054F7 83EE04              <1> 	sub	esi, 4  ; previous pointer
  3948                              <1> 
  3949 000054FA 8B06                <1> 	mov	eax, [esi]
  3950                              <1> 
  3951 000054FC 09C0                <1> 	or	eax, eax ; 0
  3952 000054FE 7407                <1> 	jz	short tloop_4
  3953                              <1> 
  3954                              <1> 	; 03/06/2020
  3955 00005500 51                  <1> 	push	ecx ; @
  3956 00005501 E8C0FFFFFF          <1> 	call	tloop
  3957 00005506 59                  <1> 	pop	ecx ; @
  3958                              <1> 	; 10/01/2022
  3959                              <1> 	;jc	short tloop_5
  3960                              <1> tloop_4:
  3961 00005507 E2EE                <1> 	loop	tloop_3
  3962                              <1> 
  3963 00005509 EB1A                <1> 	jmp	short tloop_10
  3964                              <1> 
  3965                              <1> 	; 10/01/2022
  3966                              <1> ;tloop_5:
  3967                              <1> ;	pop	edx ; ***  ; discard eax
  3968                              <1> ;	; error code in eax
  3969                              <1> ;tloop_6:
  3970                              <1> ;	pop	esi ; **
  3971                              <1> ;	pop	edi ; *
  3972                              <1> ;	retn
  3973                              <1> 	
  3974                              <1> 	; free blocks in current indirect block
  3975                              <1> tloop_7:
  3976                              <1> 	;mov	ecx, 512/4  ; 128 dwords
  3977 0000550B 81C6FC010000        <1> 	add	esi, 508
  3978                              <1> tloop_8:
  3979 00005511 8B06                <1> 	mov	eax, [esi]
  3980 00005513 21C0                <1> 	and	eax, eax ; 0 ?
  3981 00005515 7409                <1> 	jz	short tloop_9
  3982                              <1> 	
  3983 00005517 56                  <1> 	push	esi ; **** ; 10/01/2022
  3984 00005518 51                  <1> 	push	ecx ; *****
  3985 00005519 E8B0FCFFFF          <1> 	call	free
  3986                              <1> 		; if cf = 0 -> eax = 0
  3987                              <1> 		; if cf = 1 -> eax = error code (in al)
  3988 0000551E 59                  <1> 	pop	ecx ; *****
  3989 0000551F 5E                  <1> 	pop	esi ; **** ; 10/01/2022
  3990                              <1> 	; 10/01/2022
  3991                              <1> 	;; 07/06/2020
  3992                              <1> 	;jc	short tloop_6
  3993                              <1> tloop_9:
  3994 00005520 83EE04              <1> 	sub	esi, 4
  3995 00005523 E2EC                <1> 	loop	tloop_8
  3996                              <1> tloop_10:
  3997 00005525 58                  <1> 	pop	eax ; *** ; free indirect block's itself
  3998 00005526 E8A3FCFFFF          <1> 	call	free
  3999                              <1> 		;; if cf = 0 -> eax = 0
  4000                              <1> 		;; if cf = 1 -> eax = error code (in al)
  4001                              <1> 	; 10/01/2022
  4002                              <1> 	; (if we are here, there is not an error, cf=0) 
  4003                              <1> 	;jmp	short tloop_6
  4004                              <1> 
  4005                              <1> 	; 10/02/2022
  4006 0000552B 31C0                <1> 	xor	eax, eax ; 0
  4007 0000552D 5E                  <1> 	pop	esi ; **
  4008 0000552E 5F                  <1> 	pop	edi ; *
  4009 0000552F C3                  <1> 	retn
  4010                              <1> 
  4011                              <1> 	; Retro UNIX 386 v2.0 'imap' code
  4012                              <1> 	;	(runix v2 fs inode map)
  4013                              <1> imap:
  4014                              <1> 	; 10/01/2022 - Retro UNIX 386 v1.2
  4015                              <1> 	;	(major modification)
  4016                              <1> 	; 05/11/2021 - temporary (simplified code)
  4017                              <1> 	; 21/08/2021
  4018                              <1> 	; 15/08/2021
  4019                              <1> 	; 14/06/2021
  4020                              <1> 	; 02/05/2021
  4021                              <1> 	; 01/04/2021, 08/04/2021, 24/04/2021
  4022                              <1> 	; 29/03/2021
  4023                              <1> 	; 28/03/2021 - Retro UNIX 386 v2 (beginning)
  4024                              <1> 	;
  4025                              <1> 	; 'imap' finds the byte in inode map containing
  4026                              <1> 	; allocation bit for an i-node whose number in (E)AX
  4027                              <1> 	;
  4028                              <1> 	; (ref: 'UNIXHDCP.ASM', imap', 22/01/2020) 
  4029                              <1> 	;
  4030                              <1> 	; ((Retro UNIX 386 v2 'imap' code is mostly different
  4031                              <1> 	; than Retro UNIX 386 v1.1 'imap' code.))
  4032                              <1> 	;
  4033                              <1> 	; INPUTS ->
  4034                              <1> 	;   EAX = inode number
  4035                              <1> 	;        0 = first free inode
  4036                              <1> 	;       >0 = requested inode
  4037                              <1> 	;   [cdev] = current (logical) drive/device
  4038                              <1> 	;	
  4039                              <1> 	; OUTPUTS ->
  4040                              <1> 	;    EBX = address of the byte contains allocation bit
  4041                              <1> 	;     DX has 1 at calculated bit position
  4042                              <1> 	;   ; 05/11/2021	
  4043                              <1> 	;    EBP = superblock buffer address  
  4044                              <1> 	;    (EAX = inode number)	  	
  4045                              <1> 	;   ; 08/04/2021
  4046                              <1> 	;     If cf=1 -> error code in eax (al) 	
  4047                              <1> 	;
  4048                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp
  4049                              <1> 
  4050                              <1> 	; 05/11/2021
  4051 00005530 803D[856E0000]00    <1> 	cmp	byte [cdev], 0
  4052 00005537 7616                <1> 	jna	short imap_0
  4053                              <1> 	; 10/01/2022
  4054 00005539 BD[5C710000]        <1> 	mov	ebp, mount ; mounted fs superblock buffer
  4055 0000553E EB14                <1> 	jmp	short imap_1
  4056                              <1> 
  4057                              <1> imap_ialloc_err:
  4058                              <1> 	; 10/01/2022
  4059 00005540 C705[186F0000]2100- <1> 	mov	dword [u.error], ERR_INO_ALLOC ; 33
  4059 00005548 0000                <1>
  4060                              <1> 			; 'inode allocation error !'
  4061 0000554A E95DE6FFFF          <1> 	jmp	error
  4062                              <1>  
  4063                              <1> imap_0:
  4064                              <1> 	; 10/01/2022
  4065 0000554F BD[546F0000]        <1> 	mov	ebp, systm ; root fs superblock buffer
  4066                              <1> imap_1:
  4067                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4068                              <1> imap_x:
  4069                              <1> 	; 05/11/2021
  4070                              <1> 	; 21/08/2021
  4071                              <1> 	; 15/08/2021 (Retro UNIX 386 v2)
  4072                              <1> 	; call from 'maknod2' ; 10/01/2022
  4073                              <1> 	;
  4074                              <1> 	; eax = inode number
  4075                              <1> 	; [cdev] = device number for inode in eax
  4076                              <1> 	; ebp = superblock buffer address
  4077                              <1> 
  4078                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4079                              <1> 	; 'imap' and 'imap_x' will return with..
  4080                              <1> 	;    ECX = byte offset from inode map buff (imap_x)
  4081                              <1> 	;    EBX = byte addr of the byte with allocation bit
  4082                              <1> 	;    EDX (DL) has a 1 in the calculated bit position
  4083                              <1> 
  4084                              <1> 	; 02/05/2021
  4085                              <1> 	; convert inode number to first free inode if it is 0
  4086 00005554 E83D000000          <1> 	call	imap_3 ; 10/01/2022
  4087 00005559 72E5                <1> 	jc	short imap_ialloc_err
  4088                              <1> 	; eax = inode number > 1 (1 = root directory inode)
  4089                              <1> 
  4090 0000555B 898584000000        <1> 	mov	[ebp+SB.LastInode], eax
  4091                              <1> 	
  4092 00005561 50                  <1> 	push	eax ; * ; save inode number
  4093                              <1> 
  4094                              <1> 	; convert inode number to inode map sector index
  4095 00005562 E847000000          <1> 	call	imap_8 ; 10/01/2022
  4096 00005567 50                  <1> 	push	eax ; ** ; byte offset in inode map buffer
  4097                              <1> 
  4098                              <1> 	; edx = inode map buffer sector index number (< 16)
  4099                              <1> 	; eax = byte offset in inode map buffer (< 512)
  4100                              <1> 
  4101                              <1> 	; 15/08/2021
  4102 00005568 89958C000000        <1> 	mov	[ebp+SB.ImapIndex], edx
  4103 0000556E 8B4520              <1> 	mov	eax, [ebp+SB.InodeMapAddr]
  4104 00005571 01D0                <1> 	add	eax, edx
  4105 00005573 034504              <1> 	add	eax, [ebp+SB.BootSectAddr]
  4106                              <1> 	; eax = physical sector number
  4107                              <1> 	; [cdev] = current device/disk number
  4108                              <1> 	
  4109                              <1> 	; 10/01/2022 (Retro UNIX 386 v1.2)
  4110 00005576 55                  <1> 	push	ebp ; ***
  4111 00005577 E8A5090000          <1> 	call	dskrd
  4112 0000557C 5D                  <1> 	pop	ebp ; ***
  4113                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  4114                              <1> 	; eax = physical sector number
  4115                              <1> 	; ebx = buffer data address
  4116                              <1> 
  4117                              <1> 	; 10/01/2022
  4118 0000557D 8A4C2404            <1> 	mov	cl, [esp+4] ; * ; inode number
  4119                              <1> 	;dec	cl
  4120 00005581 31D2                <1> 	xor	edx, edx
  4121                              <1> 	;mov	dl, 1
  4122 00005583 FEC2                <1> 	inc	dl ; dl = 1
  4123                              <1> 	;and	ecx, 7
  4124                              <1> 	; 02/05/2021
  4125 00005585 FEC9                <1> 	dec	cl
  4126 00005587 7405                <1> 	jz	short imap_2 ; 15/08/2021
  4127 00005589 80E107              <1> 	and	cl, 7	; 1 imap bytes is for 8 inodes 
  4128 0000558C D2E2                <1> 	shl	dl, cl
  4129                              <1> imap_2:
  4130                              <1> 	; 10/01/2022
  4131                              <1> 	; save physical sector number of imap sector in the SB
  4132 0000558E 89457C              <1> 	mov	[ebp+SB.ImapBuffer], eax ; ! sector addr !
  4133                              <1> 	; 
  4134 00005591 59                  <1> 	pop	ecx ; ** ; byte offset in inode map buffer
  4135 00005592 01CB                <1> 	add	ebx, ecx ; + byte position
  4136 00005594 58                  <1> 	pop	eax ; * ; inode number
  4137                              <1> 
  4138                              <1> 	; 10/01/2022
  4139                              <1> 	; ECX contains byte offset from inode map buff (imap_x)
  4140                              <1> 	; EDX (DL) has a 1 in the calculated bit position
  4141                              <1> 	; EBX has byte address of the byte with allocation bit
  4142                              <1> 
  4143 00005595 C3                  <1> 	retn
  4144                              <1> 
  4145                              <1> imap_3:
  4146                              <1> 	; 10/01/2022
  4147                              <1> 	; 15/08/2021
  4148                              <1> 	; 02/05/2021
  4149                              <1> 	; 28/03/2021
  4150                              <1> 	; get first free inode number (from superblock)
  4151                              <1> 	; and check inode number against inode count
  4152                              <1> 	;
  4153                              <1> 	; INPUT:
  4154                              <1> 	;    eax = 0 -> get first free inode number
  4155                              <1> 	;    (eax > 0 -> check inode number)
  4156                              <1> 	;    ebp = superblock address ; 15/08/2021
  4157                              <1> 	; OUTPUT:
  4158                              <1> 	;    eax = inode number 
  4159                              <1> 	;    (eax will be 2 when SB.FirstFreeIno is invalid)
  4160                              <1> 	;    cf = 1 -> inode allocation error/problem
  4161                              <1> 	
  4162 00005596 21C0                <1> 	and	eax, eax	
  4163 00005598 750E                <1> 	jnz	short imap_5
  4164                              <1> 
  4165                              <1> 	; get first free inode
  4166                              <1> 	;mov	eax, [ebp+SB.FreeInodes]
  4167                              <1> 	;and	eax, eax
  4168                              <1> 	;jz	short imap_6
  4169                              <1> 	; 10/01/2022
  4170 0000559A 394530              <1> 	cmp	[ebp+SB.FreeInodes], eax ; 0
  4171 0000559D 760D                <1> 	jna	short imap_6	
  4172 0000559F 8B4534              <1> 	mov	eax, [ebp+SB.FirstFreeIno] ; 1 based inode num
  4173 000055A2 40                  <1> 	inc	eax
  4174 000055A3 7502                <1> 	jnz	short imap_4 ; 0FFFFFFFFh -> 0
  4175                              <1> 	; invalid first free inode value (not initialized)
  4176 000055A5 B003                <1> 	mov	al, 3 ; first free inode to be searched + 1
  4177                              <1> imap_4:
  4178 000055A7 48                  <1> 	dec	eax
  4179                              <1> imap_5:
  4180                              <1> 	; 15/08/2021
  4181                              <1> 	; check inode number against inode count of the fs
  4182 000055A8 394514              <1> 	cmp	[ebp+SB.InodeCount], eax
  4183 000055AB C3                  <1> 	retn	; if cf = 1 --> inode number > inode count
  4184                              <1> imap_6:
  4185                              <1> 	; 'imap' inode allocation error !
  4186 000055AC F9                  <1> 	stc
  4187                              <1> imap_7:
  4188 000055AD C3                  <1> 	retn
  4189                              <1> 
  4190                              <1> imap_8:
  4191                              <1> 	; 10/01/2022
  4192                              <1> 	; 15/08/2021
  4193                              <1> 	; 02/05/2021
  4194                              <1> 	; 28/03/2021
  4195                              <1> 	; convert inode count to inode map sector index
  4196                              <1> 	;
  4197                              <1> 	; INPUT: 
  4198                              <1> 	;    eax = inode number
  4199                              <1> 	; OUTPUT:
  4200                              <1> 	;    edx = inode map sector offset/index number
  4201                              <1> 	;    eax = byte offset from start of imapbuf	 
  4202                              <1> 
  4203 000055AE 31D2                <1> 	xor	edx, edx
  4204 000055B0 48                  <1> 	dec	eax ; zero based inode number
  4205 000055B1 74FA                <1> 	jz	short imap_7
  4206                              <1> 
  4207 000055B3 C1E803              <1> 	shr	eax, 3 ; 8 inodes per inode map byte
  4208                              <1> 		; eax = byte offset from start of inode map
  4209 000055B6 88E2                <1> 	mov	dl, ah ; ah <= 31 (1Fh) for Retro UNIX 386 v2
  4210 000055B8 D0EA                <1> 	shr	dl, 1
  4211                              <1> 		; edx = inode map sector offset/index number
  4212                              <1> 	;and	eax, 511
  4213 000055BA 6625FF01            <1> 	and	ax, 511
  4214                              <1> 		; eax = byte offset from start of imapbuf
  4215 000055BE C3                  <1> 	retn
  2081                                  %include 'u6.s'      ; 31/05/2015
  2082                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2083                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2084                              <1> ; ****************************************************************************
  2085                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC
  2086                              <1> ; Last Modification: 31/12/2021
  2087                              <1> ; ----------------------------------------------------------------------------
  2088                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2089                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2090                              <1> ;
  2091                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2092                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2093                              <1> ; <Bell Laboratories (17/3/1972)>
  2094                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2095                              <1> ;
  2096                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2097                              <1> ;
  2098                              <1> ; ****************************************************************************
  2099                              <1> 
  2100                              <1> 	; 25/12/2021
  2101                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2102                              <1> readi:
  2103                              <1> 	; 20/05/2015
  2104                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2105                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2106                              <1> 	;
  2107                              <1> 	; Reads from an inode whose number in R1
  2108                              <1> 	; 
  2109                              <1> 	; INPUTS ->
  2110                              <1> 	;    r1 - inode number
  2111                              <1> 	;    u.count - byte count user desires
  2112                              <1> 	;    u.base - points to user buffer
  2113                              <1> 	;    u.fofp - points to word with current file offset
  2114                              <1> 	; OUTPUTS ->
  2115                              <1> 	;    u.count - cleared
  2116                              <1> 	;    u.nread - accumulates total bytes passed back
  2117                              <1> 	;
  2118                              <1> 	; ((AX = R1)) input/output
  2119                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2120                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2121                              <1> 
  2122 000055BF 31D2                <1> 	xor	edx, edx ; 0
  2123 000055C1 8915[D06E0000]      <1> 	mov 	[u.nread], edx ; 0
  2124                              <1> 		; clr u.nread / accumulates number of bytes transmitted
  2125 000055C7 668915[106F0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2126 000055CE 3915[CC6E0000]      <1> 	cmp 	[u.count], edx ; 0
  2127                              <1> 		; tst u.count / is number of bytes to be read greater than 0
  2128 000055D4 7701                <1> 	ja 	short readi_1 ; 1f
  2129                              <1> 		; bgt 1f / yes, branch
  2130 000055D6 C3                  <1> 	retn
  2131                              <1> 		; rts r0 / no, nothing to read; return to caller
  2132                              <1> readi_1: ; 1:
  2133                              <1> 	;	; mov r1,-(sp) / save i-number on stack
  2134                              <1> 	;cmp	ax, 40
  2135                              <1> 	;	; cmp r1,$40. / want to read a special file 
  2136                              <1> 	;	;             / (i-nodes 1,...,40 are for special files)
  2137                              <1>         ;ja	dskr 
  2138                              <1> 	;	; ble 1f / yes, branch
  2139                              <1> 	;	; jmp dskr / no, jmp to dskr; 
  2140                              <1> 	;	;         / read file with i-node number (r1)
  2141                              <1> 	;	;    / starting at byte ((u.fofp)), read in u.count bytes
  2142                              <1> 	
  2143                              <1> 	; 28/11/2021
  2144 000055D7 F605[166F0000]FF    <1> 	test	byte [u.kcall], 0FFh
  2145 000055DE 7505                <1> 	jnz	short readi_2  ; 'readi' called by 'namei'
  2146                              <1> 
  2147                              <1> 	; eax = inode number
  2148                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2149 000055E0 E88BFCFFFF          <1> 	call	iget
  2150                              <1> readi_2:
  2151                              <1> 	; 28/11/2021
  2152                              <1> 	; eax = inode number
  2153                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2154 000055E5 E882040000          <1> 	call	is_regular_file
  2155                              <1> 	;jz	dskr ; regular file 
  2156                              <1> 	; 25/12/2021
  2157 000055EA 7505                <1> 	jnz	short readi_5 ; device file 
  2158                              <1> 	; regular file
  2159 000055EC E9E4000000          <1> 	jmp	dskr
  2160                              <1> readi_5:
  2161                              <1> 	; (20/05/2015)
  2162 000055F1 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2163                              <1> 
  2164                              <1> 	; 28/11/2021	
  2165                              <1> 	; device file
  2166 000055F2 BB[0C560000]        <1> 	mov	ebx, readi_4
  2167 000055F7 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2168 000055FA 720E                <1> 	jb	short readi_3
  2169 000055FC 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2170 000055FF 7709                <1> 	ja	short readi_3	
  2171                              <1> 	
  2172                              <1> 	; convert v2 inode number to v1 device inode number
  2173 00005601 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2174 00005603 89C1                <1> 	mov	ecx, eax
  2175 00005605 C0E102              <1> 	shl	cl, 2 ; * 4
  2176 00005608 01CB                <1> 	add	ebx, ecx
  2177                              <1> readi_3:
  2178 0000560A FF23                <1> 	jmp	dword [ebx]	
  2179                              <1> 		 ; jmp *1f-2(r1)
  2180                              <1> readi_4: ; 1:
  2181 0000560C [5C560000]          <1> 	dd	null ; 28/11/2021
  2182 00005610 [60560000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2183                              <1> 		 ;rtty / tty; r1=2
  2184                              <1> 		 ;rppt / ppt; r1=4
  2185 00005614 [B1560000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2186                              <1> 		 ;rmem / mem; r1=6
  2187                              <1> 		 ;rrf0 / rf0
  2188                              <1> 		 ;rrk0 / rk0
  2189                              <1> 		 ;rtap / tap0
  2190                              <1> 		 ;rtap / tap1
  2191                              <1> 		 ;rtap / tap2
  2192                              <1> 		 ;rtap / tap3
  2193                              <1> 		 ;rtap / tap4
  2194                              <1> 		 ;rtap / tap5
  2195                              <1> 		 ;rtap / tap6
  2196                              <1> 		 ;rtap / tap7
  2197 00005618 [C75D0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2198 0000561C [C75D0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2199 00005620 [C75D0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2200 00005624 [C75D0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2201 00005628 [C75D0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2202 0000562C [C75D0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2203 00005630 [C6560000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2204 00005634 [AD560000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2205                              <1> 		 ;rcvt / tty0
  2206 00005638 [AD560000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2207                              <1> 		 ;rcvt / tty1
  2208 0000563C [AD560000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2209                              <1> 		 ;rcvt / tty2
  2210 00005640 [AD560000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2211                              <1> 		 ;rcvt / tty3
  2212 00005644 [AD560000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2213                              <1> 		 ;rcvt / tty4
  2214 00005648 [AD560000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2215                              <1> 		 ;rcvt / tty5
  2216 0000564C [AD560000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2217                              <1> 		 ;rcvt / tty6
  2218 00005650 [AD560000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2219                              <1> 		 ;rcvt / tty7
  2220 00005654 [AD560000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2221                              <1> 		 ;rcrd / crd
  2222 00005658 [AD560000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2223                              <1> 
  2224                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2225                              <1> null:
  2226 0000565C 31C0                <1> 	xor	eax, eax
  2227 0000565E 58                  <1> 	pop	eax
  2228 0000565F C3                  <1> 	retn
  2229                              <1> 
  2230                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2231                              <1> rtty: ; / read from console tty
  2232                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2233                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2234                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2235                              <1> 	;	     must be written immediate on video page (screen)
  2236                              <1> 	;	     when it is required.	
  2237                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2238                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2239                              <1> 	;
  2240                              <1> 	; Console tty buffer is PC keyboard buffer
  2241                              <1> 	; and keyboard-keystroke handling is different than original
  2242                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2243                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2244                              <1> 	;
  2245                              <1> 	; 06/12/2013
  2246 00005660 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2247 00005667 8A83[DF6B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2248                              <1> rttys:
  2249                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2250                              <1> 	               ; / of the control and status block
  2251                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2252                              <1> 		       ; / tty buffer
  2253                              <1> 	; 28/07/2013
  2254 0000566D A2[D96E0000]        <1> 	mov 	[u.ttyn], al
  2255                              <1> 	; 13/01/2014
  2256 00005672 FEC0                <1> 	inc	al
  2257 00005674 A2[DA6E0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2258                              <1> rtty_nc: ; 01/02/2014
  2259                              <1> 	; 29/09/2013
  2260 00005679 B90A000000          <1> 	mov	ecx, 10
  2261                              <1> rtty_1: 	; 01/02/2014
  2262                              <1> 	;push 	cx ; 29/09/2013
  2263                              <1> 	; 11/12/2021
  2264 0000567E 51                  <1> 	push	ecx
  2265                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2266 0000567F B001                <1> 	mov 	al, 1
  2267 00005681 E8A00B0000          <1> 	call 	getc
  2268                              <1> 	;pop 	cx ; 29/09/2013	
  2269                              <1> 	; 11/12/2021
  2270 00005686 59                  <1> 	pop	ecx
  2271 00005687 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 00005689 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2275                              <1> 	; 05/10/2013
  2276 0000568B 8A25[D96E0000]      <1> 	mov	ah, [u.ttyn]
  2277                              <1> 	; 29/09/2013
  2278 00005691 E8ECF7FFFF          <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 00005696 EBE1                <1> 	jmp	short rtty_nc ; 01/02/2014
  2283                              <1> 
  2284                              <1> rtty_idle:
  2285                              <1> 	; 29/07/2013
  2286 00005698 E852F7FFFF          <1> 	call 	idle
  2287 0000569D 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 0000569F 30C0                <1> 	xor 	al, al
  2297 000056A1 E8800B0000          <1> 	call 	getc
  2298 000056A6 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 000056AB 58                  <1> 	pop	eax  ; (20/05/2015)
  2304 000056AC 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 000056AD 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 000056AF EBBC                <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 000056B1 8B35[B86E0000]      <1> 	mov     esi, [u.fofp]
  2339                              <1> rmem_1:
  2340 000056B7 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 000056B9 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 000056BB 8A03                <1> 	mov	al, [ebx]
  2347                              <1> 		; movb (r1),r1 / get character from memory file, 
  2348                              <1> 		             ; / put it in r1
  2349 000056BD 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 000056C2 75F3                <1> 	jnz	short rmem_1
  2353                              <1> ret_:
  2354 000056C4 58                  <1> 	pop	eax ; 09/06/2015
  2355 000056C5 C3                  <1> 	retn
  2356                              <1> 
  2357                              <1> rlpr:
  2358                              <1> ;1:
  2359                              <1> ;rcrd:
  2360 000056C6 C705[186F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2360 000056CE 0000                <1>
  2361 000056D0 E9D7E4FFFF          <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 000056D5 50                  <1> 	push	eax
  2376                              <1> 		; mov (sp),r1 / i-number in r1
  2377                              <1> 	; AX = i-number
  2378 000056D6 E895FBFFFF          <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 000056DB 8B15[486B0000]      <1> 	mov	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2384                              <1> 	;
  2385 000056E1 8B1D[B86E0000]      <1> 	mov	ebx, [u.fofp]
  2386 000056E7 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 000056E9 7709                <1> 	ja	short dskr_1
  2392                              <1> 	;
  2393                              <1> dskr_retn: ; 12/10/2015
  2394 000056EB 58                  <1> 	pop	eax
  2395 000056EC C605[166F0000]00    <1> 	mov	byte [u.kcall], 0
  2396 000056F3 C3                  <1> 	retn	
  2397                              <1> dskr_1: 
  2398 000056F4 3B15[CC6E0000]      <1> 	cmp     edx, [u.count] 
  2399                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2400                              <1> 			       ; / to carry out read
  2401 000056FA 7306                <1> 	jnb	short dskr_2
  2402                              <1> 		; bhis 1f
  2403 000056FC 8915[CC6E0000]      <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 00005702 E804F8FFFF          <1> 	call	mget_r
  2412                              <1> 
  2413                              <1> 	; eax = physical block number
  2414                              <1> 	; [cdev] = current device number 
  2415 00005707 E815080000          <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 0000570C 803D[166F0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2420 00005713 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2421 00005715 66833D[106F0000]00  <1> 	cmp	word [u.pcount], 0
  2422 0000571D 7705                <1> 	ja	short dskr_4
  2423                              <1> dskr_3:
  2424                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2425 0000571F 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 00005724 E8C2020000          <1> 	call	sioreg
  2429                              <1> 		; jsr r0,sioreg
  2430 00005729 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 0000572B 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 0000572D 09C0                <1> 	or	eax, eax
  2443 0000572F 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2444                              <1> 	; 03/08/2013
  2445                              <1> 	;pop	eax
  2446 00005731 390D[CC6E0000]      <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 00005737 76B2                <1> 	jna	short dskr_retn
  2455 00005739 58                  <1> 	pop	eax  ; (i-node number)
  2456 0000573A 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 0000573C 66833D[106F0000]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 00005744 7705                <1> 	ja	short passc_3
  2473                              <1> 	; 08/06/2015 - 10/07/2015
  2474 00005746 E82C000000          <1> 	call	trans_addr_w
  2475                              <1> passc_3:
  2476                              <1> 	; 19/05/2015
  2477 0000574B 66FF0D[106F0000]    <1> 	dec	word [u.pcount]
  2478                              <1> 	;
  2479 00005752 8B1D[0C6F0000]      <1> 	mov	ebx, [u.pbase]
  2480 00005758 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 0000575A FF05[C86E0000]      <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 00005760 FF05[0C6F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2487 00005766 FF05[D06E0000]      <1> 	inc	dword [u.nread]
  2488                              <1> 		; inc u.nread / increment the number of bytes read
  2489 0000576C FF0D[CC6E0000]      <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 00005772 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 diasbled 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 00005773 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2515 00005775 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 00005777 29D2                <1> 	sub	edx, edx
  2552 00005779 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2553                              <1> trans_addr_rw:
  2554 0000577B 50                  <1> 	push	eax
  2555 0000577C 53                  <1> 	push	ebx
  2556                              <1> 	; 18/10/2015
  2557 0000577D 52                  <1> 	push 	edx ; r/w sign (in DL)
  2558                              <1> 	;
  2559 0000577E 8B1D[C86E0000]      <1> 	mov	ebx, [u.base]
  2560 00005784 E8CBDAFFFF          <1> 	call	get_physical_addr ; get physical address
  2561 00005789 730A                <1> 	jnc	short passc_0
  2562 0000578B A3[186F0000]        <1> 	mov	[u.error], eax
  2563                              <1> 	;pop	edx
  2564                              <1> 	;pop 	ebx
  2565                              <1> 	;pop	eax
  2566 00005790 E917E4FFFF          <1> 	jmp	error
  2567                              <1> passc_0:
  2568 00005795 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2569 00005798 5A                  <1> 	pop	edx ; 18/10/2015
  2570 00005799 7517                <1> 	jnz	short passc_1
  2571                              <1> 	; 18/10/2015
  2572 0000579B 20D2                <1> 	and 	dl, dl
  2573 0000579D 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 0000579F 51                  <1> 	push 	ecx
  2578                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2 (BugFix)
  2579 000057A0 53                  <1> 	push	ebx ;* ; BugFix  ; 31/12/2021
  2580 000057A1 E81DDAFFFF          <1> 	call 	copy_page
  2581 000057A6 5B                  <1> 	pop	ebx ;* ; BugFix  ; 31/12/2021
  2582 000057A7 59                  <1> 	pop	ecx
  2583 000057A8 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 000057AA 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2590                              <1> 	;mov 	ecx, PAGE_SIZE
  2591                              <1> 	;sub	ecx, ebx 
  2592 000057B0 01D8                <1> 	add	eax, ebx  
  2593                              <1> passc_1: 
  2594                              <1> 	; 18/10/2015
  2595                              <1> 	; 20/05/2015
  2596 000057B2 A3[0C6F0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2597 000057B7 66890D[106F0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2598 000057BE 5B                  <1> 	pop	ebx
  2599 000057BF 58                  <1> 	pop	eax
  2600 000057C0 C3                  <1> 	retn	; 08/06/2015
  2601                              <1> passc_2:
  2602 000057C1 C705[186F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2602 000057C9 0000                <1>
  2603                              <1> 	;pop 	ebx
  2604                              <1> 	;pop	eax
  2605 000057CB E9DCE3FFFF          <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 000057D0 31C9                <1> 	xor	ecx, ecx
  2630 000057D2 890D[D06E0000]      <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 000057D8 66890D[106F0000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2634 000057DF 390D[CC6E0000]      <1> 	cmp 	[u.count], ecx
  2635                              <1> 	;	; tst u.count / test the byte count specified by the user
  2636 000057E5 7701                <1> 	ja 	short writei_1 ; 1f
  2637                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2638 000057E7 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 000057E8 F605[166F0000]FF    <1> 	test	byte [u.kcall], 0FFh
  2650 000057EF 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 000057F1 E87AFAFFFF          <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 000057F6 E871020000          <1> 	call	is_regular_file
  2660                              <1> 	;jz	dskw ; regular file 
  2661                              <1> 	; 25/12/2021
  2662 000057FB 7505                <1> 	jnz	short writei_5 ; device file 
  2663                              <1> 	; regular file
  2664 000057FD E9FD000000          <1> 	jmp	dskw
  2665                              <1> writei_5:
  2666                              <1> 	; (20/05/2015)
  2667 00005802 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2668                              <1> 	
  2669                              <1> 	; 28/11/2021	
  2670                              <1> 	; device file
  2671 00005803 BB[1D580000]        <1> 	mov	ebx, writei_4
  2672 00005808 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2673 0000580B 720E                <1> 	jb	short writei_3
  2674 0000580D 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2675 00005810 7709                <1> 	ja	short writei_3 ; 11/12/2021	
  2676                              <1> 	
  2677                              <1> 	; convert v2 inode number to v1 device inode number
  2678 00005812 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2679 00005814 89C1                <1> 	mov	ecx, eax
  2680 00005816 C0E102              <1> 	shl	cl, 2 ; * 4
  2681 00005819 01CB                <1> 	add	ebx, ecx
  2682                              <1> writei_3:
  2683 0000581B 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 0000581D [5C560000]          <1> 	dd	null ; 28/11/2021
  2688 00005821 [6D580000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2689                              <1> 		 ;wtty / tty; r1=2
  2690                              <1> 		 ;wppt / ppt; r1=4
  2691 00005825 [CF580000]          <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 00005829 [495E0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2704 0000582D [495E0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2705 00005831 [495E0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2706 00005835 [495E0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2707 00005839 [495E0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2708 0000583D [495E0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2709 00005841 [C0580000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2710 00005845 [BA580000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2711                              <1> 		 ;xmtt / tty0
  2712 00005849 [BA580000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2713                              <1> 		 ;xmtt / tty1
  2714 0000584D [BA580000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2715                              <1> 		 ;xmtt / tty2
  2716 00005851 [BA580000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2717                              <1> 		 ;xmtt / tty3
  2718 00005855 [BA580000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2719                              <1> 		 ;xmtt / tty4
  2720 00005859 [BA580000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2721                              <1> 		 ;xmtt / tty5
  2722 0000585D [BA580000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2723                              <1> 		 ;xmtt / tty6
  2724 00005861 [BA580000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2725                              <1> 		 ;xmtt / tty7
  2726 00005865 [BA580000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2727                              <1> 		; / wlpr / lpr
  2728 00005869 [BA580000]          <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 0000586D 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2747 00005874 8AA3[DF6B0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2748 0000587A 88E0                <1> 	mov	al, ah ; 07/07/2014
  2749                              <1> wttys:	
  2750                              <1> 	; 10/10/2013
  2751 0000587C 8825[D96E0000]      <1> 	mov 	[u.ttyn], ah
  2752                              <1> 	; 13/01/2014
  2753 00005882 FEC0                <1> 	inc	al
  2754 00005884 A2[DB6E0000]        <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 00005889 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 0000588E 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 00005890 50                  <1> 	push	eax
  2777 00005891 E8FE090000          <1> 	call	putc ; 14/05/2013
  2778 00005896 731D                <1> 	jnc	short wtty_2
  2779                              <1> 	; 18/11/2015
  2780 00005898 E852F5FFFF          <1> 	call	idle
  2781                              <1> 	;mov	ax, [esp]
  2782                              <1> 	; 11/12/2021
  2783 0000589D 8B0424              <1> 	mov	eax, [esp]
  2784 000058A0 E8EF090000          <1> 	call	putc
  2785 000058A5 730E                <1> 	jnc	short wtty_2 
  2786                              <1> 	; 02/06/2014
  2787 000058A7 8A25[D96E0000]      <1> 	mov	ah, [u.ttyn]
  2788 000058AD E8D0F5FFFF          <1> 	call	sleep
  2789                              <1> 	;pop	ax
  2790                              <1> 	; 11/12/2021
  2791 000058B2 58                  <1> 	pop	eax
  2792 000058B3 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 000058B5 58                  <1> 	pop	eax
  2804 000058B6 EBD1                <1> 	jmp	short wtty_nc
  2805                              <1> 		; br wtty
  2806                              <1> wret:	; 10/10/2013 (20/05/2015)
  2807 000058B8 58                  <1> 	pop	eax
  2808 000058B9 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 000058BA 2C0A                <1> 	sub 	al, 10
  2826                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2827                              <1> 	; 10/10/2013
  2828 000058BC 88C4                <1> 	mov	ah, al
  2829                              <1> 	; 28/07/2013
  2830 000058BE 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 000058C0 C705[186F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2838 000058C8 0000                <1>
  2839 000058CA E9DDE2FFFF          <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 000058CF 813D[0F070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2857 000058D5 [124E0000]          <1>
  2858 000058D9 7415                <1>         je      short wmem_acc_err
  2859                              <1> 	;
  2860 000058DB 8B35[B86E0000]      <1>         mov     esi, [u.fofp] 
  2861                              <1> wmem_1:
  2862 000058E1 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 000058E6 74D0                <1> 	jz	short wret ; wmem_2  
  2868 000058E8 8B1E                <1>         mov     ebx, [esi]
  2869                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2870 000058EA 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 000058EC 8803                <1> 	mov	[ebx], al	
  2874                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2875                              <1> 			        ; / assigned to it
  2876 000058EE 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 000058F0 C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2886 000058F8 0000                <1>
  2887 000058FA E9ADE2FFFF          <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 000058FF 50                  <1> 	push	eax
  2905                              <1> 	; AX = inode number
  2906 00005900 E86BF9FFFF          <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 00005905 8B1D[B86E0000]      <1>         mov     ebx, [u.fofp] 
  2910 0000590B 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 0000590D 0315[CC6E0000]      <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 00005913 3B15[486B0000]      <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 00005919 760B                <1> 	jna	short dskw_1
  2928                              <1> 		; blos 1f / no, branch
  2929 0000591B 8915[486B0000]      <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 00005921 E8E9FAFFFF          <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 00005926 E8D7F5FFFF          <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 0000592B 8B1D[B86E0000]      <1> 	mov     ebx, [u.fofp]
  2945 00005931 8B13                <1> 	mov	edx, [ebx]
  2946 00005933 81E2FF010000        <1> 	and	edx, 1FFh  
  2947                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2948 00005939 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 0000593B 813D[CC6E0000]0002- <1> 	cmp	dword [u.count], 512
  2951 00005943 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 00005945 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 00005947 E8D5050000          <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 0000594C E830060000          <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 00005951 803D[166F0000]00    <1> 	cmp	byte [u.kcall], 0
  2968 00005958 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2969                              <1> 	;
  2970 0000595A 66833D[106F0000]00  <1> 	cmp	word [u.pcount], 0
  2971 00005962 7705                <1> 	ja	short dskw_5
  2972                              <1> dskw_4:
  2973                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2974 00005964 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 00005969 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 0000596E 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 00005970 09C0                <1> 	or	eax, eax
  2994 00005972 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2995                              <1> dskw_6:
  2996 00005974 E824060000          <1> 	call	dskwr
  2997                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2998 00005979 833D[CC6E0000]00    <1>         cmp     dword [u.count], 0
  2999                              <1> 		; tst u.count / any more data to write?
  3000 00005980 77A4                <1> 	ja	short dskw_1
  3001                              <1> 		; bne 1b / yes, branch
  3002                              <1> 	; 03/08/2013
  3003 00005982 C605[166F0000]00    <1> 	mov	byte [u.kcall], 0
  3004                              <1> 	; 20/09/2013 (;;)
  3005                              <1> 	;pop	ax
  3006                              <1> 	; 28/11/2021
  3007 00005989 58                  <1> 	pop	eax  
  3008 0000598A 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 0000598B 833D[CC6E0000]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 00005992 763F                <1> 	jna	short cpass_3
  3041                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3042 00005994 FF0D[CC6E0000]      <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 0000599A 66833D[106F0000]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 000059A2 770E                <1> 	ja	short cpass_1
  3051                              <1> 	; 02/07/2015
  3052 000059A4 833D[086F0000]00    <1> 	cmp	dword [u.ppgdir], 0  ; is the caller os kernel
  3053 000059AB 7427                <1> 	je	short cpass_k 	; (sysexec, '/etc/init') ? 
  3054                              <1> 	; 08/06/2015 - 10/07/2015
  3055 000059AD E8C1FDFFFF          <1> 	call	trans_addr_r
  3056                              <1> cpass_1:
  3057                              <1> 	; 02/07/2015
  3058                              <1> 	; 24/06/2015
  3059 000059B2 66FF0D[106F0000]    <1> 	dec	word [u.pcount]
  3060                              <1> cpass_2: 
  3061                              <1> 	; 10/10/2015
  3062                              <1> 	; 02/07/2015
  3063 000059B9 8B15[0C6F0000]      <1> 	mov	edx, [u.pbase]
  3064 000059BF 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 000059C1 FF05[D06E0000]      <1> 	inc	dword [u.nread]
  3068                              <1> 		; inc u.nread / increment no. of bytes transferred
  3069 000059C7 FF05[C86E0000]      <1> 	inc	dword [u.base]
  3070                              <1> 		; inc u.base / increment the buffer address to point to the
  3071                              <1> 			   ; / next byte
  3072 000059CD FF05[0C6F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3073                              <1> cpass_3:
  3074 000059D3 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 000059D4 8B1D[C86E0000]      <1> 	mov	ebx, [u.base]
  3087 000059DA 66C705[106F0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3087 000059E2 10                  <1>
  3088 000059E3 891D[0C6F0000]      <1> 	mov	[u.pbase], ebx
  3089 000059E9 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 000059EB 8B35[B86E0000]      <1>         mov     esi, [u.fofp]
  3117 000059F1 8B3E                <1>         mov     edi, [esi]
  3118                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3119 000059F3 89F9                <1> 	mov	ecx, edi
  3120                              <1> 		; mov r2,r3 / and also to r3
  3121 000059F5 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3122                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3123 000059FB 81E7FF010000        <1> 	and	edi, 1FFh
  3124                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3125 00005A01 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 00005A03 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 00005A05 3B0D[CC6E0000]      <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 00005A0B 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 00005A0D 8B0D[CC6E0000]      <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 00005A13 803D[166F0000]00    <1> 	cmp	byte [u.kcall], 0 
  3144 00005A1A 7613                <1> 	jna	short sioreg_1
  3145                              <1> 	; 25/07/2015
  3146                              <1> 	 ; the caller is 'mkdir' or 'namei'
  3147 00005A1C A1[C86E0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3148 00005A21 A3[0C6F0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3149 00005A26 66890D[106F0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3150 00005A2D 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 00005A2F 0FB715[106F0000]    <1> 	movzx	edx, word [u.pcount]
  3156                              <1> 		; ecx and [u.pcount] are always > 0, here
  3157 00005A36 39D1                <1> 	cmp	ecx, edx	
  3158 00005A38 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3159                              <1> sioreg_2: ; 2:
  3160 00005A3A 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3161                              <1> sioreg_3:
  3162 00005A3C 010D[D06E0000]      <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 00005A42 290D[CC6E0000]      <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 00005A48 010D[C86E0000]      <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 00005A4E 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 00005A50 8B35[0C6F0000]      <1> 	mov	esi, [u.pbase]
  3176 00005A56 66290D[106F0000]    <1> 	sub	[u.pcount], cx
  3177 00005A5D 010D[0C6F0000]      <1> 	add	[u.pbase], ecx
  3178 00005A63 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 00005A64 89C8                <1> 	mov	eax, ecx
  3186 00005A66 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3187 00005A68 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3188 00005A6A 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 00005A6C 8A0D[416B0000]      <1> 	mov	cl, [i.flgs+1]
  3205 00005A72 F6C180              <1> 	test	cl, 80h		; regular file ?
  3206 00005A75 7514                <1> 	jnz	short isregf_1  ; yes 
  3207 00005A77 80E120              <1> 	and	cl, 20h 	; device file ?
  3208 00005A7A 7511                <1> 	jnz	short isregf_2  ; yes 
  3209                              <1> 
  3210                              <1> 	; 28/11/2021
  3211                              <1> 	; invalid inode/file type !
  3212 00005A7C C705[186F0000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  3212 00005A84 0000                <1>
  3213                              <1> 	;stc
  3214                              <1> 	;retn
  3215 00005A86 E921E1FFFF          <1> 	jmp	error
  3216                              <1> isregf_1:
  3217 00005A8B 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 00005A8D C3                  <1> 	retn	
  2082                                  %include 'u7.s'      ; 18/04/2015
  2083                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2084                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2085                              <1> ; ****************************************************************************
  2086                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC
  2087                              <1> ; Last Modification: 08/01/2022
  2088                              <1> ; ----------------------------------------------------------------------------
  2089                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2090                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2091                              <1> ;
  2092                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2093                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2094                              <1> ; <Bell Laboratories (17/3/1972)>
  2095                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2096                              <1> ;
  2097                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2098                              <1> ;
  2099                              <1> ; ****************************************************************************
  2100                              <1> 
  2101                              <1> sysmount: ; / mount file system; args special; name
  2102                              <1> 	; 14/11/2015
  2103                              <1> 	; 24/10/2015
  2104                              <1> 	; 13/10/2015
  2105                              <1> 	; 10/07/2015
  2106                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2107                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2108                              <1> 	;
  2109                              <1> 	; 'sysmount' anounces to the system that a removable 
  2110                              <1> 	; file system has been mounted on a special file.
  2111                              <1> 	; The device number of the special file is obtained via
  2112                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2113                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2114                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2115                              <1> 	; to read file system into core, i.e. the first block on the
  2116                              <1> 	; mountable file system is read in. This block is super block
  2117                              <1> 	; for the file system. This call is super user restricted.	
  2118                              <1> 	;
  2119                              <1> 	; Calling sequence:
  2120                              <1> 	;	sysmount; special; name
  2121                              <1> 	; Arguments:
  2122                              <1> 	;	special - pointer to name of special file (device)
  2123                              <1> 	;	name -  pointer to name of the root directory of the
  2124                              <1> 	;		newly mounted file system. 'name' should 
  2125                              <1> 	;		always be a directory.
  2126                              <1> 	; Inputs: - 
  2127                              <1> 	; Outputs: -
  2128                              <1> 	; ...............................................................
  2129                              <1> 	;				
  2130                              <1> 	; Retro UNIX 8086 v1 modification: 
  2131                              <1> 	;       'sysmount' system call has two arguments; so,
  2132                              <1> 	;	* 1st argument, special is pointed to by BX register
  2133                              <1> 	;	* 2nd argument, name is in CX register
  2134                              <1> 	;
  2135                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2136                              <1> 	;	       already modified for IBM PC compatibility and 
  2137                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2138                              <1> 	
  2139                              <1> 	;call	arg2
  2140                              <1> 		; jsr r0,arg2 / get arguments special and name
  2141 00005A8E 891D[C06E0000]      <1> 	mov	[u.namep], ebx
  2142 00005A94 51                  <1> 	push	ecx ; directory name
  2143 00005A95 66833D[906E0000]00  <1> 	cmp	word [mnti], 0
  2144                              <1> 		; tst mnti / is the i-number of the cross device file
  2145                              <1> 			 ; / zero?
  2146                              <1> 	;ja	error
  2147                              <1>         	; bne errora / no, error
  2148 00005A9D 0F87E9000000        <1> 	ja	sysmnt_err0
  2149                              <1> 	;
  2150 00005AA3 E8CC000000          <1> 	call	getspl
  2151                              <1> 		; jsr r0,getspl / get special files device number in r1
  2152                              <1> 	; 13/10/2015
  2153 00005AA8 0FB7D8              <1> 	movzx	ebx, ax ; ; Retro UNIX 8086 v1 device number (0 to 5)
  2154 00005AAB F683[EA680000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2155 00005AB2 750F                <1> 	jnz	short sysmnt_1
  2156                              <1> sysmnt_err1:
  2157 00005AB4 C705[186F0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2157 00005ABC 0000                <1>
  2158 00005ABE E9E9E0FFFF          <1> 	jmp	error
  2159                              <1> sysmnt_1:
  2160 00005AC3 8F05[C06E0000]      <1> 	pop	dword [u.namep]
  2161                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2162                              <1> 				  ; / on the device
  2163                              <1> 	; 14/11/2015
  2164 00005AC9 53                  <1> 	push	ebx ; 13/10/2015
  2165                              <1> 		; mov r1,-(sp) / save the device number
  2166                              <1>         ;
  2167 00005ACA E813EEFFFF          <1> 	call	namei
  2168                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2169                              <1> 		       ; ax = 0 -> file not found 	
  2170                              <1> 	;jz	error
  2171                              <1> 	;jc	error
  2172                              <1> 		; jsr r0,namei / get the i-number of the file
  2173                              <1>                	; br errora
  2174 00005ACF 730F                <1> 	jnc	short sysmnt_2
  2175                              <1> sysmnt_err2:
  2176 00005AD1 C705[186F0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2176 00005AD9 0000                <1>
  2177 00005ADB E9CCE0FFFF          <1> 	jmp	error
  2178                              <1> sysmnt_2:	
  2179 00005AE0 66A3[906E0000]      <1> 	mov	[mnti], ax
  2180                              <1>         	; mov r1,mnti / put it in mnti
  2181                              <1> ;	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2182                              <1> sysmnt_3: ;1:
  2183                              <1>         ;cmp	byte [ebx+1], 0
  2184                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2185                              <1> 			   ; / dismountable device set?
  2186                              <1>         ;jna	short sysmnt_4		
  2187                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2188                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2189                              <1> 	;jmp	short sysmnt_3
  2190                              <1> sysmnt_4:   
  2191 00005AE6 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2192 00005AE7 A2[876E0000]        <1> 	mov	[mdev], al
  2193                              <1> 		; mov  (sp),mntd / no, put the device number in mntd
  2194 00005AEC 8803                <1> 	mov	[ebx], al
  2195                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2196                              <1> 			      ; / of the I/O queue entry
  2197                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2198                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2199 00005AEE 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2200                              <1> 		; bis $2000,sb1 / set the read bit
  2201                              <1> 	; Retro UNIX 386 v1 modification : 
  2202                              <1> 	;	32 bit block number at buffer header offset 4
  2203 00005AF3 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2204 00005AFA E8E1050000          <1> 	call 	diskio
  2205 00005AFF 731C                <1> 	jnc	short sysmnt_5
  2206 00005B01 31C0                <1> 	xor 	eax, eax
  2207 00005B03 66A3[906E0000]      <1> 	mov	[mnti], ax ; 0
  2208 00005B09 A2[876E0000]        <1> 	mov	[mdev], al ; 0
  2209                              <1> 	;mov	[cdev], al ; 0
  2210                              <1> sysmnt_invd:
  2211                              <1> 	; 14/11/2015
  2212 00005B0E FEC8                <1> 	dec 	al
  2213 00005B10 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2214 00005B12 FEC0                <1> 	inc	al
  2215 00005B14 48                  <1> 	dec	eax
  2216 00005B15 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2217 00005B18 E98FE0FFFF          <1> 	jmp	error
  2218                              <1> sysmnt_5:
  2219                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2220                              <1> 	; (Following check is needed to prevent mounting an
  2221                              <1> 	; in valid valid file system (in valid super block).
  2222                              <1> 	; 
  2223 00005B1D 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2224 00005B20 C0E002              <1> 	shl	al, 2 ; 4*index
  2225 00005B23 8B88[CE680000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2226 00005B29 C1E103              <1> 	shl 	ecx, 3
  2227 00005B2C 0FB715[58710000]    <1> 	movzx	edx, word [sb1+4] ; the 1st data word
  2228 00005B33 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2229                              <1> 			 ; (in sectors), if they are not equal
  2230                              <1> 			 ; the disk to be mounted is an...	
  2231 00005B35 75D7                <1> 	jne	short sysmnt_invd ; invalid disk !
  2232                              <1> 			 ; (which has not got a valid super block)
  2233                              <1> 	;
  2234 00005B37 C6430100            <1> 	mov	byte [ebx+1], 0
  2235                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2236                              <1> ;sysmnt_6: ;1:
  2237                              <1> 	;;cmp	byte [sb1+1], 0
  2238                              <1> 		; tstb   sb1+1 / done reading?
  2239                              <1>    	;;jna	sysret
  2240                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2241                              <1> 	;;jmp	short sysmnt_6
  2242                              <1> 		;bne 1b / no, wait
  2243                              <1>         	;br sysreta / yes
  2244 00005B3B E98CE0FFFF          <1> 	jmp	sysret
  2245                              <1> 
  2246                              <1> sysumount: ; / special dismount file system
  2247                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2248                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2249                              <1> 	;
  2250                              <1> 	; 04/11/2013
  2251                              <1> 	; 09/07/2013
  2252                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2253                              <1> 	; indicated as an argument is no longer contain a removable
  2254                              <1> 	; file system. 'getspl' gets the device number of the special
  2255                              <1> 	; file. If no file system was mounted on that device an error
  2256                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2257                              <1> 	; to 'sysret'.
  2258                              <1> 	;
  2259                              <1> 	; Calling sequence:
  2260                              <1> 	;	sysmount; special
  2261                              <1> 	; Arguments:
  2262                              <1> 	;	special - special file to dismount (device)
  2263                              <1> 	;
  2264                              <1> 	; Inputs: - 
  2265                              <1> 	; Outputs: -
  2266                              <1> 	; ...............................................................
  2267                              <1> 	;				
  2268                              <1> 	; Retro UNIX 8086 v1 modification: 
  2269                              <1> 	;       'sysumount' system call has one argument; so,
  2270                              <1> 	;	* Single argument, special is pointed to by BX register
  2271                              <1> 	;
  2272                              <1> 	
  2273                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2274                              <1> 	;call	arg
  2275                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2276 00005B40 891D[C06E0000]      <1>         mov	[u.namep], ebx
  2277 00005B46 E829000000          <1> 	call	getspl
  2278                              <1> 		; jsr r0,getspl / get the device number in r1
  2279 00005B4B 3A05[876E0000]      <1> 	cmp	al, [mdev]
  2280                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2281 00005B51 7539                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2282                              <1> 	;jne	error
  2283                              <1>         	; bne errora / no error
  2284 00005B53 30C0                <1> 	xor	al, al ; ah = 0
  2285                              <1> sysumnt_0: ;1:
  2286 00005B55 3805[55710000]      <1>      	cmp 	[sb1+1], al ; 0
  2287                              <1> 		; tstb sb1+1 / yes, is the device still doing I/O 
  2288                              <1> 			   ; / (inhibit bit set)?
  2289 00005B5B 7607                <1> 	jna	short sysumnt_1		
  2290                              <1> 		; bne 1b / yes, wait
  2291 00005B5D E88DF2FFFF          <1> 	call	idle ; (wait for hardware interrupt)
  2292 00005B62 EBF1                <1> 	jmp	short sysumnt_0
  2293                              <1> sysumnt_1:        
  2294 00005B64 A2[876E0000]        <1> 	mov	[mdev], al
  2295                              <1> 	     	; clr mntd / no, clear these
  2296 00005B69 66A3[906E0000]      <1>    	mov	[mnti], ax
  2297                              <1>         	; clr mnti
  2298 00005B6F E958E0FFFF          <1>         jmp	sysret
  2299                              <1> 		; br sysreta / return
  2300                              <1> 
  2301                              <1> getspl: ; / get device number from a special file name
  2302 00005B74 E869EDFFFF          <1> 	call	namei
  2303                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2304                              <1> 		       ; ax = 0 -> file not found 	
  2305 00005B79 0F8252FFFFFF        <1>         jc      sysmnt_err2 ; 'file not found !' error
  2306                              <1> 	;jz	error
  2307                              <1> 	;jc	error
  2308                              <1> 		; jsr r0,namei / get the i-number of the special file
  2309                              <1>                 ; br errora / no such file
  2310 00005B7F 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2311                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2312                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2313 00005B83 7207                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2314                              <1> 	;jc	error
  2315                              <1> 		; ble errora / less than 0?  yes, error
  2316 00005B85 6683F805            <1>         cmp	ax, 5 ;
  2317                              <1> 		; cmp  r1,$9. / greater than 9  tap 7
  2318 00005B89 7701                <1> 	ja	short sysmnt_err0 ; 'permission denied !' error
  2319                              <1> 	;ja	error
  2320                              <1>         	; bgt errora / yes, error
  2321                              <1>         ; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2322                              <1> iopen_retn:
  2323 00005B8B C3                  <1> 	retn
  2324                              <1> 		; rts    r0 / return with device number in r1
  2325                              <1> sysmnt_err0:
  2326 00005B8C C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2326 00005B94 0000                <1>
  2327 00005B96 E911E0FFFF          <1> 	jmp	error
  2328                              <1> 
  2329                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2330                              <1> iopen:
  2331                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2332                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  2333                              <1> 	; 19/05/2015
  2334                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2335                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2336                              <1> 	;
  2337                              <1> 	; open file whose i-number is in r1
  2338                              <1> 	; 
  2339                              <1> 	; INPUTS ->
  2340                              <1> 	;    r1 - inode number
  2341                              <1> 	; OUTPUTS ->
  2342                              <1> 	;    file's inode in core	
  2343                              <1> 	;    r1 - inode number (positive)
  2344                              <1> 	;
  2345                              <1> 	; ((AX = R1))
  2346                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2347                              <1> 	;        
  2348                              <1> ; / open file whose i-number is in r1
  2349                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2350                              <1> ;		;tst r1 / write or read access?
  2351                              <1> ;       jnz	short iopen_2
  2352                              <1> ;		;blt 2f / write, go to 2f
  2353                              <1> ;	mov	dl, 2 ; read access
  2354                              <1> ;	call	access
  2355                              <1> ;       	;jsr r0,access; 2 
  2356                              <1> ;	; / get inode into core with read access
  2357                              <1> ;	; DL=2
  2358                              <1> ;iopen_0:
  2359                              <1> ;       cmp	ax, 40
  2360                              <1> ;		; cmp r1,$40. / is it a special file
  2361                              <1> ;       ja	short iopen_retn
  2362                              <1> ;		;bgt  3f / no. 3f
  2363                              <1> 
  2364                              <1> 	; 05/12/2021
  2365                              <1> 	; DL = 0 -> open for read
  2366                              <1> 	; DL = 1 -> open for write
  2367                              <1> 
  2368 00005B9B 52                  <1> 	push	edx ; *
  2369                              <1> 
  2370                              <1> 	; set permission/mode flag for 'access' 
  2371                              <1> 	;	(DX = 100h -> IREAD, DX = 80h -> IWRITE)
  2372                              <1> 
  2373 00005B9C B601                <1> 	mov	dh, 1
  2374 00005B9E 08D2                <1> 	or	dl, dl ; dl = 0, open for read	
  2375 00005BA0 7404                <1> 	jz	short iopen_0 ; DX = IREAD (100h)
  2376                              <1> 	; dl = 1, open for write 
  2377 00005BA2 FECE                <1> 	dec	dh
  2378 00005BA4 B280                <1> 	mov	dl, 80h
  2379                              <1> 	; DX = IWRITE (80h)
  2380                              <1> iopen_0:
  2381                              <1> 	; 27/03/2021
  2382                              <1> 	;   EAX = inode number (in AX)
  2383                              <1> 	;    DX = access mode, 100h = read, 80h = write
  2384                              <1> 
  2385                              <1> 	; 24/06/2020 - Retro UNIX 386 v2	
  2386 00005BA6 E8AFF7FFFF          <1> 	call	access
  2387                              <1> 		;jsr r0,access; 1 / get inode in core
  2388                              <1> 	
  2389                              <1> 	; 27/03/2021
  2390                              <1> 	; DX return value from 'access' subroutine
  2391                              <1> 	;    may be 100h, 20h, 04h for DX = 100h (IREAD) input
  2392                              <1> 	;	     80h, 10h, 02h for DX = 80h (IWRITE) input
  2393                              <1> 
  2394                              <1> 	; 05/12/2021
  2395 00005BAB 5A                  <1> 	pop	edx ; * ; dl = 0 -> open for read
  2396                              <1> 			; dl = 1 -> open for write
  2397                              <1> 	; 24/06/2020
  2398 00005BAC 8A0D[416B0000]      <1> 	mov	cl, [i.flgs+1]
  2399                              <1> 
  2400 00005BB2 F6C180              <1> 	test	cl, 80h		; regular file ?
  2401 00005BB5 7514                <1> 	jnz	short iopen_1	; yes ; 05/12/2021
  2402 00005BB7 F6C120              <1> 	test	cl, 20h 	; device file ?
  2403 00005BBA 7524                <1> 	jnz	short iopen_2	; yes
  2404                              <1> 
  2405                              <1> 	; no !?, error.
  2406                              <1> 
  2407 00005BBC C705[186F0000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  2407 00005BC4 0000                <1>
  2408                              <1> iopen_err:
  2409 00005BC6 E9E1DFFFFF          <1> 	jmp	error
  2410                              <1> 
  2411                              <1> iopen_1:
  2412                              <1> 	; 05/12/2021
  2413                              <1> 	; (If open mode is 'write' and the file/inode is a directory,
  2414                              <1> 	;  open request will/must be rejected.)
  2415                              <1> 	;
  2416                              <1> 	; (If inode is a regular file and it is not a directory,
  2417                              <1> 	; there is nothing to do here, we need to return to 'sysopen'
  2418                              <1> 	; for completing the rest of file opening procedure.) 
  2419                              <1> 	
  2420 00005BCB F6C140              <1> 	test	cl, 40h	; directory ?
  2421 00005BCE 74BB                <1> 	jz	short iopen_retn ; no
  2422                              <1> 	
  2423 00005BD0 20D2                <1> 	and	dl, dl ; open mode is 1 (write) ?
  2424 00005BD2 74B7                <1> 	jz	short iopen_retn ; no
  2425                              <1> 
  2426                              <1> 	; !!!	
  2427                              <1> 	; 'sysopen' for writing
  2428                              <1> 	;	 is not applicable for directories
  2429                              <1> 	; (Directory entries must be created or deleted by
  2430                              <1> 	; relevant system calls.)
  2431                              <1> 
  2432                              <1> 	;mov	dword [u.error], ERR_DIR_ACCESS ; 11
  2433 00005BD4 C705[186F0000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; 11
  2433 00005BDC 0000                <1>
  2434                              <1> 				; 'permission denied !' error  
  2435                              <1> 	;jmp	error
  2436 00005BDE EBE6                <1> 	jmp	short iopen_err
  2437                              <1> 
  2438                              <1> ;iopen_retn:
  2439                              <1> ;	retn
  2440                              <1> 
  2441                              <1> iopen_2:
  2442                              <1> 	;push	ax
  2443                              <1> 	;	; mov r1,-(sp) / yes, figure out
  2444                              <1> 	;movzx	ebx, al
  2445                              <1> 	;shl	bx, 2
  2446                              <1> 	;	; asl r1
  2447                              <1>         ;add	ebx, iopen_1 - 4
  2448                              <1> 	;jmp	dword [ebx]
  2449                              <1>         ;	; jmp *1f-2(r1) / which one and transfer to it
  2450                              <1> 	
  2451                              <1> 	; 05/12/2021
  2452 00005BE0 50                  <1> 	push	eax ; save inode number
  2453                              <1> 	; device file
  2454 00005BE1 BB[FD5B0000]        <1> 	mov	ebx, iopen_4
  2455 00005BE6 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2456 00005BE9 720E                <1> 	jb	short iopen_3
  2457 00005BEB 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2458 00005BEE 7709                <1> 	ja	short iopen_3	
  2459                              <1> 	; convert v2 inode number to v1 device inode number
  2460 00005BF0 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2461 00005BF2 89C1                <1> 	mov	ecx, eax
  2462 00005BF4 C0E102              <1> 	shl	cl, 2 ; * 4
  2463 00005BF7 01CB                <1> 	add	ebx, ecx
  2464                              <1> iopen_3:
  2465 00005BF9 FEC2                <1> 	inc	dl ; 1 = read, 2 = write
  2466 00005BFB FF23                <1> 	jmp	dword [ebx]	
  2467                              <1> 		 ; jmp *1f-2(r1)
  2468                              <1> ;iopen_1: ; 1:
  2469                              <1> iopen_4:
  2470 00005BFD [5C560000]          <1> 	dd	null ; 05/12/2021
  2471 00005C01 [4D5C0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2472                              <1>  		 ;otty / tty ; r1=2
  2473                              <1>         	 ;oppt / ppt ; r1=4
  2474 00005C05 [EC5C0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2475                              <1> 		 ;sret / mem ; r1=6
  2476                              <1> 		 ;sret / rf0
  2477                              <1>         	 ;sret / rk0
  2478                              <1>         	 ;sret / tap0
  2479                              <1>         	 ;sret / tap1
  2480                              <1>         	 ;sret / tap2
  2481                              <1>         	 ;sret / tap3
  2482                              <1>         	 ;sret / tap4
  2483                              <1>         	 ;sret / tap5
  2484                              <1>         	 ;sret / tap6
  2485                              <1>         	 ;sret / tap7
  2486 00005C09 [EC5C0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2487 00005C0D [EC5C0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2488 00005C11 [EC5C0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2489 00005C15 [EC5C0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2490 00005C19 [EC5C0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2491 00005C1D [EC5C0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2492                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2493 00005C21 [EC5C0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2494 00005C25 [5C5C0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2495                              <1> 		 ;ocvt / tty0
  2496 00005C29 [5C5C0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2497                              <1> 		 ;ocvt / tty1
  2498 00005C2D [5C5C0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2499                              <1> 		 ;ocvt / tty2
  2500 00005C31 [5C5C0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2501                              <1> 		 ;ocvt / tty3
  2502 00005C35 [5C5C0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2503                              <1> 		 ;ocvt / tty4
  2504 00005C39 [5C5C0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2505                              <1> 		 ;ocvt / tty5
  2506 00005C3D [5C5C0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2507                              <1> 		 ;ocvt / tty6
  2508 00005C41 [5C5C0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2509                              <1> 		 ;ocvt / tty7
  2510 00005C45 [5C5C0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2511                              <1> 		 ;error / crd
  2512 00005C49 [5C5C0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2513                              <1> 
  2514                              <1> ;iopen_2: ; 2: / check open write access
  2515                              <1> ;	neg	ax
  2516                              <1> ;		;neg r1 / make inode number positive
  2517                              <1> ;	mov	dl, 1 ; write access
  2518                              <1> ;	call	access
  2519                              <1> ;		;jsr r0,access; 1 / get inode in core
  2520                              <1> ;	; DL=1
  2521                              <1> ;	test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2522                              <1> ;		;bit $40000,i.flgs / is it a directory?
  2523                              <1> ;	jz	short iopen_0
  2524                              <1> ;	;mov	[u.error], ERR_DIR_ACCESS
  2525                              <1> ;	;jmp	error ; permission denied !
  2526                              <1> ;	jmp	sysmnt_err0
  2527                              <1> ;	;;jnz	error		
  2528                              <1> ;      		; bne 2f / yes, transfer (error)
  2529                              <1> ;       ;;jmp     short iopen_0
  2530                              <1> ;	;cmp	ax, 40
  2531                              <1> ;		; cmp r1,$40. / no, is it a special file?
  2532                              <1> ;        ;ja	short iopen_2
  2533                              <1> ;		 ;bgt 3f / no, return
  2534                              <1> ;	;push	ax
  2535                              <1> ;		;mov r1,-(sp) / yes
  2536                              <1> ;	;movzx	ebx, al
  2537                              <1> ;	;shl	bx, 1
  2538                              <1> ;		; asl r1
  2539                              <1> ;	;add	ebx, ipen_3 - 2
  2540                              <1> ;	;jmp	dword [ebx]
  2541                              <1> ;		; jmp *1f-2(r1) / figure out 
  2542                              <1> ;			; / which special file it is and transfer
  2543                              <1> ;iopen_3: ; 1:
  2544                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2545                              <1> ; 		 ;otty / tty ; r1=2
  2546                              <1> ;        	 ;leadr / ppt ; r1=4
  2547                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2548                              <1> ;		 ;sret / mem ; r1=6
  2549                              <1> ;		 ;sret / rf0
  2550                              <1> ;        	 ;sret / rk0
  2551                              <1> ;        	 ;sret / tap0
  2552                              <1> ;        	 ;sret / tap1
  2553                              <1> ;        	 ;sret / tap2
  2554                              <1> ;        	 ;sret / tap3
  2555                              <1> ;        	 ;sret / tap4
  2556                              <1> ;        	 ;sret / tap5
  2557                              <1> ;        	 ;sret / tap6
  2558                              <1> ;        	 ;sret / tap7
  2559                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2560                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2561                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2562                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2563                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2564                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2565                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2566                              <1> ;	;dd	ejec ; lpr, AX = 9  (runix)
  2567                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2568                              <1> ;		 ;ocvt / tty0
  2569                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2570                              <1> ;		 ;ocvt / tty1
  2571                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2572                              <1> ;		 ;ocvt / tty2
  2573                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2574                              <1> ;		 ;ocvt / tty3
  2575                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2576                              <1> ;		 ;ocvt / tty4
  2577                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2578                              <1> ;		 ;ocvt / tty5
  2579                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2580                              <1> ;		 ;ocvt / tty6
  2581                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2582                              <1> ;		 ;ocvt / tty7
  2583                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2584                              <1> ;		 ;/ ejec / lpr
  2585                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2586                              <1> 
  2587                              <1> otty: ;/ open console tty for reading or writing
  2588                              <1> 	; 08/01/2022
  2589                              <1> 	; 01/01/2022
  2590                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2591                              <1> 	; 16/11/2015
  2592                              <1> 	; 12/11/2015
  2593                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2594                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2595                              <1> 	; 16/07/2013
  2596                              <1> 	; Retro UNIX 8086 v1 modification:
  2597                              <1> 	;  If a tty is open for read or write by
  2598                              <1> 	;     a process (u.uno), only same process can open
  2599                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2600                              <1> 	;
  2601                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2602                              <1> 	;
  2603 00005C4D 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2604 00005C54 8A83[DF6B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2605                              <1> 	; 13/01/2014
  2606 00005C5A EB04                <1> 	jmp	short ottyp
  2607                              <1> ocvt:
  2608 00005C5C 2C0A                <1> 	sub	al, 10
  2609                              <1> 	; 08/01/2022
  2610 00005C5E 31DB                <1> 	xor	ebx, ebx
  2611                              <1> ottyp:
  2612                              <1> 	; 08/01/2022
  2613                              <1> 	; 01/01/2022
  2614                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2615                              <1> 	; 16/11/2015
  2616                              <1> 	; 12/11/2015
  2617                              <1> 	; 18/05/2015 (32 bit modifications)
  2618                              <1> 	; 06/12/2013 - 13/07/2014
  2619 00005C60 88C6                <1> 	mov	dh, al ; tty number
  2620                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2621                              <1> 	; 08/01/2022
  2622 00005C62 88C3                <1> 	mov	bl, al
  2623 00005C64 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2624                              <1> 	; 26/01/2014	
  2625 00005C66 81C3[F46D0000]      <1> 	add 	ebx, ttyl
  2626 00005C6C 668B0B              <1> 	mov 	cx, [ebx]
  2627                              <1> 		   ; CL = lock value (0 or process number)
  2628                              <1> 		   ; CH = open count 
  2629 00005C6F 20C9                <1> 	and 	cl, cl
  2630                              <1> 	; 13/01/2014
  2631                              <1> 	;jz 	short otty_ret
  2632                              <1> 	; 05/12/2021
  2633 00005C71 743A                <1> 	jz 	short ottys_0
  2634                              <1> 	;
  2635                              <1> 	; 16/11/2015
  2636 00005C73 3A0D[F56E0000]      <1> 	cmp 	cl, [u.uno]
  2637 00005C79 745D                <1> 	je	short ottys_3
  2638                              <1> 	;
  2639 00005C7B 0FB6D9              <1> 	movzx 	ebx, cl ; the process which has locked the tty
  2640 00005C7E D0E3                <1> 	shl 	bl, 1
  2641 00005C80 668B83[7E6B0000]    <1> 	mov 	ax, [ebx+p.pid-2]
  2642                              <1> 	;movzx 	ebx, byte [u.uno]
  2643 00005C87 8A1D[F56E0000]      <1> 	mov	bl, [u.uno]
  2644 00005C8D D0E3                <1> 	shl 	bl, 1
  2645 00005C8F 663B83[9E6B0000]    <1> 	cmp 	ax, [ebx+p.ppid-2]
  2646 00005C96 7440                <1> 	je 	short ottys_3  ; 16/11/2015
  2647                              <1> 	;
  2648                              <1> 	; the tty is locked by another process
  2649                              <1> 	; except the parent process (p.ppid)
  2650                              <1>         ;
  2651 00005C98 C705[186F0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2651 00005CA0 0000                <1>
  2652                              <1> 			; permission denied ! error
  2653                              <1> otty_err: ; 13/01/2014
  2654 00005CA2 08D2                <1> 	or 	dl, dl ; DL = 0 -> called by sysstty
  2655                              <1> 	;jnz	error
  2656                              <1> 	; 05/12/2021
  2657 00005CA4 7405                <1> 	jz	short otty_stc_retn
  2658 00005CA6 E901DFFFFF          <1> 	jmp	error
  2659                              <1> otty_stc_retn:
  2660 00005CAB F9                  <1> 	stc
  2661 00005CAC C3                  <1> 	retn
  2662                              <1> ottys_0:
  2663                              <1> 	; 05/12/2021
  2664                              <1> otty_ret:
  2665                              <1> 	; 13/01/2014
  2666 00005CAD 80FE07              <1> 	cmp 	dh, 7
  2667 00005CB0 761C                <1> 	jna	short ottys_2
  2668                              <1> 	; 16/11/2015
  2669                              <1> com_port_check:
  2670 00005CB2 BE[126E0000]        <1> 	mov	esi, com1p
  2671 00005CB7 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2672 00005CBA 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2673 00005CBC 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2674                              <1> ottys_1:
  2675                              <1> 	; 12/11/2015
  2676 00005CBD 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2677 00005CC0 770C                <1> 	ja	short com_port_ready
  2678                              <1> 	;
  2679 00005CC2 C705[186F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2679 00005CCA 0000                <1>
  2680                              <1> 			   ; device not ready ! error
  2681 00005CCC EBD4                <1> 	jmp	short otty_err	 
  2682                              <1> com_port_ready:
  2683                              <1> ottys_2:
  2684 00005CCE 08C9                <1> 	or	cl, cl  ; cl = lock/owner, ch = open count
  2685 00005CD0 7506                <1> 	jnz	short ottys_3
  2686 00005CD2 8A0D[F56E0000]      <1> 	mov	cl, [u.uno]
  2687                              <1> ottys_3:
  2688 00005CD8 FEC5                <1> 	inc 	ch
  2689 00005CDA 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2690                              <1> 	; 06/12/2013
  2691 00005CDD FEC6                <1> 	inc	dh ; tty number + 1
  2692 00005CDF BB[DA6E0000]        <1> 	mov	ebx, u.ttyp
  2693                              <1> 	; 13/01/2014
  2694                              <1> 	;test	dl, 2 ; open for read sign
  2695                              <1> 	;jnz	short ottys_4
  2696                              <1> 	; 05/12/2021
  2697                              <1> 	;test	dl, 2
  2698                              <1> 	;jz	short ottys_4 ; open for read
  2699                              <1> 	; 01/01/2022
  2700 00005CE4 F6C201              <1> 	test	dl, 1
  2701 00005CE7 7501                <1> 	jnz	short ottys_4 ; open for read
  2702                              <1> 	; dl = 2 (open for write) or dl = 0 (sysstty)  
  2703 00005CE9 43                  <1> 	inc	ebx
  2704                              <1> ottys_4:
  2705                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2706 00005CEA 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2707                              <1> sret:
  2708 00005CEC 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2709 00005CEE 7401                <1> 	jz	short iclose_retn
  2710                              <1> 	;pop 	ax
  2711                              <1> 	; 05/12/2021
  2712 00005CF0 58                  <1> 	pop	eax
  2713                              <1> iclose_retn:	
  2714 00005CF1 C3                  <1> 	retn
  2715                              <1> 
  2716                              <1> 	;
  2717                              <1> 	; Original UNIX v1 'otty' routine:
  2718                              <1> 	;	
  2719                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2720                              <1>         ;                 / reader status reg
  2721                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2722                              <1>         ;                 / punch status reg
  2723                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2724                              <1>         ;                          / console tty buffer
  2725                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2726                              <1>         ;            / console tty
  2727                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2728                              <1>         ;             / buffer header
  2729                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2730                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2731                              <1>         ;                 / tty
  2732                              <1>         ;br     sret / ?
  2733                              <1> ;sret:
  2734                              <1> 		;clr *$ps / set processor priority to zero
  2735                              <1> ;	pop	ax
  2736                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2737                              <1> ;3:
  2738                              <1> ;	retn
  2739                              <1>         	;rts r0
  2740                              <1> 	
  2741                              <1> ;ocvt:	; < open tty >
  2742                              <1> 	; 13/01/2014
  2743                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2744                              <1> 	; 24/09/2013 consistency check -> ok
  2745                              <1> 	; 16/09/2013
  2746                              <1> 	; 03/09/2013
  2747                              <1> 	; 27/08/2013
  2748                              <1> 	; 16/08/2013
  2749                              <1> 	; 16/07/2013
  2750                              <1> 	; 27/05/2013
  2751                              <1> 	; 21/05/2013
  2752                              <1> 	;
  2753                              <1> 	; Retro UNIX 8086 v1 modification !
  2754                              <1> 	; 
  2755                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2756                              <1> 	;		(exactly different than this one)
  2757                              <1> 	;	was in 'u9.s' file.
  2758                              <1> 	;
  2759                              <1> 	; 16/07/2013
  2760                              <1> 	; Retro UNIX 8086 v1 modification:
  2761                              <1> 	;  If a tty is open for read or write by
  2762                              <1> 	;     a process (u.uno), only same process can open
  2763                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2764                              <1> 	;
  2765                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2766                              <1> 
  2767                              <1> 	; 16/09/2013
  2768                              <1> 	; sub 	al, 10
  2769                              <1> 	
  2770                              <1> 	; 06/12/2013
  2771                              <1> 	;cmp	al, 7
  2772                              <1>         ;jna	short ottyp
  2773                              <1> 	; 13/01/2014
  2774                              <1> 	;jmp	short ottyp
  2775                              <1> 
  2776                              <1> ;oppt: / open paper tape for reading or writing
  2777                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2778                              <1> ;        tstb   pptiflg / is file already open
  2779                              <1> ;        bne    2f / yes, branch
  2780                              <1> ;1:
  2781                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2782                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2783                              <1> ;               br .+4 / for paper tape input and place in free list
  2784                              <1> ;        br     1b
  2785                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2786                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2787                              <1> ;        br     sret
  2788                              <1> ;2:
  2789                              <1> ;        jmp    error / file already open
  2790                              <1> 
  2791                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2792                              <1> iclose:
  2793                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2794                              <1> 	; 10/04/2021
  2795                              <1> 	; 08/04/2021
  2796                              <1> 	; 04/04/2021 - Retro UNIX 386 v2
  2797                              <1> 	; 19/05/2015
  2798                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2799                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2800                              <1> 	;
  2801                              <1> 	; close file whose i-number is in r1
  2802                              <1> 	; 
  2803                              <1> 	; INPUTS ->
  2804                              <1> 	;    r1 - inode number
  2805                              <1> 	; OUTPUTS ->
  2806                              <1> 	;    file's inode in core	
  2807                              <1> 	;    r1 - inode number (positive)
  2808                              <1> 	;
  2809                              <1> 	; ((AX = R1))
  2810                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2811                              <1> 	;        
  2812                              <1> ;;/ close file whose i-number is in r1
  2813                              <1> ;	mov	dl, 2 ; 12/01/2014
  2814                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2815                              <1> ;		;tst r1 / test i-number
  2816                              <1> ;	;jnz	short iclose_2
  2817                              <1> ;		;blt 2f / if neg., branch
  2818                              <1> ;	jz	short iclose_0 ; 30/07/2013
  2819                              <1> ;	; 16/07/2013 
  2820                              <1> ;	neg	ax ; make it positive
  2821                              <1> ;	; 12/01/2014
  2822                              <1> ;	dec	dl ; dl = 1 (open for write)
  2823                              <1> ;iclose_0:
  2824                              <1> ;	cmp	ax, 40
  2825                              <1> ;		;cmp r1,$40. / is it a special file
  2826                              <1> ;       ja	short iclose_retn  ; 13/01/2014
  2827                              <1> ;		;bgt 3b / no, return
  2828                              <1> ;	; 12/01/2014
  2829                              <1> ;	; DL=2 -> special file was opened for reading
  2830                              <1> ;	; DL=1 -> special file was opened for writing
  2831                              <1> 
  2832                              <1> 	; 04/04/2021
  2833                              <1> 	; INPUT:
  2834                              <1> 	;	(e)ax = inode number
  2835                              <1> 	;	   dl = open mode
  2836                              <1> 	;		0 = control mode
  2837                              <1> 	;		1 = read
  2838                              <1> 	;		2 = write
  2839                              <1> 	; OUTPUT:
  2840                              <1> 	;	none
  2841                              <1> 	;	(if cf=1 -> eax = error code)
  2842                              <1> 	;	(if cf=0 -> ax = inode number)
  2843                              <1> 
  2844                              <1> 	; 10/04/2021
  2845                              <1>         ; Modified registers: ebx, ecx, edx, esi, edi, (ebp) 
  2846                              <1> 
  2847                              <1> 	; 05/12/2021
  2848                              <1> 	; 08/04/2021
  2849                              <1> 
  2850 00005CF2 52                  <1> 	push	edx
  2851 00005CF3 E878F5FFFF          <1> 	call	iget
  2852 00005CF8 5A                  <1> 	pop	edx 
  2853                              <1> 
  2854 00005CF9 8A0D[416B0000]      <1> 	mov	cl, [i.flgs+1]
  2855                              <1> 
  2856                              <1> 	; if i.flgs bit 15 is 1, it is regular file 
  2857                              <1> 	;test	byte [i.flgs+1], 80h ; is it a special file?
  2858 00005CFF F6C180              <1> 	test	cl, 80h ; is it a special file?
  2859 00005D02 75ED                <1> 	jnz	short iclose_retn ; no
  2860                              <1> 
  2861                              <1> 	;; inode flags - bit 13 must be 1 
  2862                              <1> 	;test	cl, 20h ; is it a valid device inode
  2863                              <1> 	;jnz	short iclose_retn ; no
  2864                              <1> 	
  2865                              <1> 	;push	ax
  2866                              <1> 	;	;mov r1,-(sp) / yes, save r1 on stack
  2867                              <1> 	;movzx	ebx, al
  2868                              <1> 	;shl	bx, 2
  2869                              <1> 	;	; asl r1
  2870                              <1> 	;add	ebx, iclose_1 - 4
  2871                              <1> 	;jmp	dword [ebx]
  2872                              <1> 	;	; jmp *1f-2(r1) / compute jump address and transfer
  2873                              <1> 
  2874                              <1> 	; 05/12/2021
  2875 00005D04 50                  <1> 	push	eax ; save inode number
  2876                              <1> 	; device file
  2877 00005D05 BB[1F5D0000]        <1> 	mov	ebx, iclose_1
  2878 00005D0A 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2879 00005D0D 720E                <1> 	jb	short iclose_0
  2880 00005D0F 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2881 00005D12 7709                <1> 	ja	short iclose_0
  2882                              <1> 	; convert v2 inode number to v1 device inode number
  2883 00005D14 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2884 00005D16 89C1                <1> 	mov	ecx, eax
  2885 00005D18 C0E102              <1> 	shl	cl, 2 ; * 4
  2886 00005D1B 01CB                <1> 	add	ebx, ecx
  2887                              <1> iclose_0:
  2888 00005D1D FF23                <1> 	jmp	dword [ebx]	
  2889                              <1> 		 ; jmp *1f-2(r1)
  2890                              <1> iclose_1: ; 1:
  2891 00005D1F [5C560000]          <1> 	dd	null ; 05/12/2021
  2892 00005D23 [6F5D0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2893 00005D27 [C15D0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2894 00005D2B [C15D0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2895 00005D2F [C15D0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2896 00005D33 [C15D0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2897 00005D37 [C15D0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2898 00005D3B [C15D0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2899 00005D3F [C15D0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2900 00005D43 [C15D0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2901                              <1> 	;dd	error; lpr, AX = 9 (error!)
  2902                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2903 00005D47 [7E5D0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2904 00005D4B [7E5D0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2905 00005D4F [7E5D0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2906 00005D53 [7E5D0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2907 00005D57 [7E5D0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2908 00005D5B [7E5D0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2909 00005D5F [7E5D0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2910 00005D63 [7E5D0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2911 00005D67 [7E5D0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2912 00005D6B [7E5D0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2913                              <1> 
  2914                              <1> 	; 1:
  2915                              <1> 	;        ctty   / tty
  2916                              <1> 	;        cppt   / ppt
  2917                              <1> 	;        sret   / mem
  2918                              <1> 	;        sret   / rf0
  2919                              <1> 	;        sret   / rk0
  2920                              <1> 	;        sret   / tap0
  2921                              <1> 	;        sret   / tap1
  2922                              <1> 	;        sret   / tap2
  2923                              <1> 	;        sret   / tap3
  2924                              <1> 	;        sret   / tap4
  2925                              <1> 	;        sret   / tap5
  2926                              <1> 	;        sret   / tap6
  2927                              <1> 	;        sret   / tap7
  2928                              <1> 	;        ccvt   / tty0
  2929                              <1> 	;        ccvt   / tty1
  2930                              <1> 	;        ccvt   / tty2
  2931                              <1> 	;        ccvt   / tty3
  2932                              <1> 	;        ccvt   / tty4
  2933                              <1> 	;        ccvt   / tty5
  2934                              <1> 	;        ccvt   / tty6
  2935                              <1> 	;        ccvt   / tty7
  2936                              <1> 	;        error / crd
  2937                              <1> 
  2938                              <1> ;iclose_2: ; 2: / negative i-number
  2939                              <1> 	;neg	ax
  2940                              <1> 		;neg r1 / make it positive
  2941                              <1> 	;cmp	ax, 40
  2942                              <1> 		;cmp r1,$40. / is it a special file?
  2943                              <1>         ;ja	short @b
  2944                              <1> 		;bgt    3b / no. return
  2945                              <1> 	;push	ax
  2946                              <1> 		;mov r1,-(sp)
  2947                              <1> 	;movzx	ebx, al
  2948                              <1> 	;shl	bx, 1
  2949                              <1> 		;asl r1 / yes. compute jump address and transfer
  2950                              <1> 	;add	ebx, iclose_3 - 2
  2951                              <1> 	;jmp	dword [ebx]
  2952                              <1> 		;jmp *1f-2(r1) / figure out 
  2953                              <1> ;iclose_3:
  2954                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2955                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2956                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2957                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2958                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2959                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2960                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2961                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2962                              <1> 	;;dd	sret ; lpr, AX = 9	
  2963                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2964                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2965                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2966                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2967                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2968                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2969                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2970                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2971                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2972                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2973                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2974                              <1> 	
  2975                              <1> 	;1:
  2976                              <1> 	;      	ctty   / tty
  2977                              <1> 	;       leadr  / ppt
  2978                              <1> 	;       sret   / mem
  2979                              <1> 	;       sret   / rf0
  2980                              <1> 	;       sret   / rk0
  2981                              <1> 	;       sret   / tap0
  2982                              <1> 	;       sret   / tap1
  2983                              <1> 	;       sret   / tap2
  2984                              <1> 	;       sret   / tap3
  2985                              <1> 	;       sret   / tap4
  2986                              <1> 	;       sret   / tap5
  2987                              <1> 	;       sret   / tap6
  2988                              <1> 	;       sret   / tap7
  2989                              <1> 	;       ccvt   / tty0
  2990                              <1> 	;       ccvt   / tty1
  2991                              <1> 	;       ccvt   / tty2
  2992                              <1> 	;       ccvt   / tty3
  2993                              <1> 	;       ccvt   / tty4
  2994                              <1> 	;       ccvt   / tty5
  2995                              <1> 	;       ccvt   / tty6
  2996                              <1> 	;       ccvt   / tty7
  2997                              <1> 	;/       ejec / lpr
  2998                              <1> 
  2999                              <1> ctty: ; / close console tty
  3000                              <1> 	; 08/01/2022
  3001                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3002                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3003                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3004                              <1> 	;
  3005                              <1> 	; Retro UNIX 8086 v1 modification !
  3006                              <1> 	; (DL = 2 -> it is open for reading)
  3007                              <1> 	; (DL = 1 -> it is open for writing)
  3008                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3009                              <1> 	;
  3010                              <1> 	; 06/12/2013
  3011 00005D6F 0FB61D[F56E0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3012 00005D76 8A83[DF6B0000]      <1>         mov     al, [ebx+p.ttyc-1]
  3013                              <1> 	; 13/01/2014
  3014 00005D7C EB04                <1> 	jmp	short cttyp
  3015                              <1> ccvt:
  3016 00005D7E 2C0A                <1> 	sub 	al, 10
  3017                              <1> 	; 08/01/2022
  3018 00005D80 31DB                <1> 	xor	ebx, ebx
  3019                              <1> cttyp:	
  3020                              <1> 	; 08/01/2022
  3021                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  3022                              <1> 	; 18/05/2015 (32 bit modifications)
  3023                              <1> 	; 16/08/2013 - 26/01/2014
  3024                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3025                              <1> 	; 08/01/2022
  3026 00005D82 88C3                <1> 	mov	bl, al
  3027 00005D84 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3028                              <1> 	; 26/01/2014
  3029 00005D86 81C3[F46D0000]      <1> 	add 	ebx, ttyl
  3030 00005D8C 88C6                <1> 	mov 	dh, al ; tty number
  3031 00005D8E 668B03              <1> 	mov 	ax, [ebx]
  3032                              <1> 		   ; AL = lock value (0 or process number)
  3033                              <1> 		   ; AH = open count 
  3034 00005D91 20E4                <1> 	and 	ah, ah
  3035 00005D93 750F                <1> 	jnz	short ctty_ret
  3036 00005D95 C705[186F0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3036 00005D9D 0000                <1>
  3037                              <1> 			; device not open ! error
  3038                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3039 00005D9F E908DEFFFF          <1> 	jmp	error
  3040                              <1> 	; 26/01/2014
  3041                              <1> ctty_ret:
  3042 00005DA4 FECC                <1> 	dec 	ah ; decrease open count
  3043 00005DA6 7502                <1> 	jnz	short ctty_1
  3044 00005DA8 30C0                <1> 	xor	al, al ; unlock/free tty
  3045                              <1> ctty_1:
  3046 00005DAA 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3047                              <1> 	;
  3048 00005DAD BB[DA6E0000]        <1> 	mov	ebx, u.ttyp
  3049                              <1> 	;test	dl, 1 ; open for write sign
  3050                              <1> 	;jz	short ctty_2
  3051                              <1> 	; 05/12/2021
  3052 00005DB2 F6C202              <1> 	test	dl, 2 ; open for write sign
  3053 00005DB5 7401                <1> 	jz	short ctty_2	
  3054 00005DB7 43                  <1> 	inc	ebx
  3055                              <1> ctty_2:
  3056 00005DB8 FEC6                <1> 	inc	dh ; tty number + 1
  3057 00005DBA 3A33                <1> 	cmp	dh, [ebx]
  3058 00005DBC 7503                <1> 	jne	short cret
  3059                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3060 00005DBE C60300              <1> 	mov	byte [ebx], 0
  3061                              <1> cret:
  3062 00005DC1 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3063 00005DC3 7401                <1> 	jz	short ctty_3
  3064                              <1> 	;pop	ax
  3065                              <1> 	; 05/12/2021
  3066 00005DC5 58                  <1> 	pop	eax
  3067                              <1> ctty_3:
  3068 00005DC6 C3                  <1> 	retn
  3069                              <1> 
  3070                              <1> ;ctty_err: ; 13/01/2014
  3071                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3072                              <1> ;	jnz	error
  3073                              <1> ;	stc
  3074                              <1> ;	retn
  3075                              <1> 
  3076                              <1> 	; Original UNIX v1 'ctty' routine:
  3077                              <1> 	;	
  3078                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3079                              <1> 	;		;/ point r5 to the console tty buffer
  3080                              <1>         ;decb   (r5) / dec number of processes using console tty
  3081                              <1>         ;br     sret / return via sret
  3082                              <1> 
  3083                              <1> ;ccvt:	; < close tty >
  3084                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3085                              <1> 	;
  3086                              <1> 	; Retro UNIX 8086 v1 modification !
  3087                              <1> 	; 
  3088                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3089                              <1> 	;		(exactly different than this one)
  3090                              <1> 	;	was in 'u9.s' file.
  3091                              <1> 	;
  3092                              <1> 	; DL = 2 -> it is open for reading
  3093                              <1> 	; DL = 1 -> it is open for writing
  3094                              <1> 	;
  3095                              <1> 	; 17/09/2013
  3096                              <1> 	;sub 	al, 10
  3097                              <1> 	;cmp	al, 7
  3098                              <1> 	;jna	short cttyp
  3099                              <1> 	; 13/01/2014
  3100                              <1> 	;jmp	short cttyp
  3101                              <1> 
  3102                              <1> ;cppt: / close paper tape
  3103                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3104                              <1> ;1:
  3105                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3106                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3107                              <1> ;                          / and assign to free list
  3108                              <1> ;               br sret
  3109                              <1> ;        br     1b
  3110                              <1> 
  3111                              <1> ;ejec:	
  3112                              <1> ;	jmp	error
  3113                              <1> ;/ejec:
  3114                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3115                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3116                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3117                              <1> ;/       br     sret / return to caller via 'sret'
  2083                                  %include 'u8.s'      ; 11/06/2015
  2084                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2085                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2086                              <1> ; ****************************************************************************
  2087                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  2088                              <1> ; Last Modification: 09/01/2022
  2089                              <1> ; ----------------------------------------------------------------------------
  2090                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2091                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2092                              <1> ;
  2093                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2094                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2095                              <1> ; <Bell Laboratories (17/3/1972)>
  2096                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2097                              <1> ;
  2098                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2099                              <1> ;
  2100                              <1> ; ****************************************************************************
  2101                              <1> 
  2102                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2103                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2104                              <1> ;; Word 1, byte 0 = device id
  2105                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2106                              <1> ;;          bit 9 = write bit
  2107                              <1> ;;	    bit 10 = read bit	  
  2108                              <1> ;;	    bit 12 = waiting to write bit	
  2109                              <1> ;;	    bit 13 = waiting to read bit
  2110                              <1> ;;	    bit 15 = inhibit bit
  2111                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2112                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2113                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2114                              <1> ;;
  2115                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2116                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2117                              <1> ;;
  2118                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2119                              <1> ;; Word 1, Byte 0 = device id
  2120                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2121                              <1> ;;          bit 9 = write bit
  2122                              <1> ;;	    bit 10 = read bit	  
  2123                              <1> ;;	    bit 12 = waiting to write bit	
  2124                              <1> ;;	    bit 13 = waiting to read bit
  2125                              <1> ;;	    bit 15 = inhibit bit
  2126                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2127                              <1> ;;
  2128                              <1> ;; Original UNIX v1 ->
  2129                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2130                              <1> ;; Original UNIX v1 -> 
  2131                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2132                              <1> ;;
  2133                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2134                              <1> ;;
  2135                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2136                              <1> ;;          0 = fd0
  2137                              <1> ;;	    1 = fd1
  2138                              <1> ;;	    2 = hd0
  2139                              <1> ;;	    3 = hd1
  2140                              <1> ;;	    4 = hd2
  2141                              <1> ;;	    5 = hd3
  2142                              <1> 
  2143                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2144                              <1> 
  2145                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2146                              <1> 	; 26/04/2013
  2147                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2148                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2149                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2150                              <1> 
  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> 	; 14/07/2015
  2159                              <1> 	; 10/07/2015
  2160                              <1> 	; 09/06/2015
  2161                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2162                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2163                              <1> 	;	
  2164                              <1> 	; / read a block from a block structured device
  2165                              <1> 	;
  2166                              <1> 	; INPUTS ->
  2167                              <1> 	;    [u.fopf] points to the block number
  2168                              <1> 	;    CX = maximum block number allowed on device
  2169                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2170                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2171                              <1> 	;    [u.count]	number of bytes to read in
  2172                              <1> 	; OUTPUTS ->
  2173                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2174                              <1> 	;    [u.fopf] points to next consecutive block to be read
  2175                              <1> 	;
  2176                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2177                              <1> 	;
  2178                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2179                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2180                              <1> 	;	is increased by 1. For example: If user/program request 
  2181                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2182                              <1> 	;  	the next block number just as 512 byte reading is done.
  2183                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2184                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2185                              <1> 	;       enough to keep byte position/offset of the disk), this
  2186                              <1> 	;	defect will not be corrected, user/program must request
  2187                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2188                              <1> 	;       for achieving correct result. In future version(s), 
  2189                              <1> 	;	this defect will be corrected by using different 
  2190                              <1> 	;       user (u) structure.  26/07/2013 - Erdogan Tan 	
  2191                              <1> 
  2192                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2193                              <1> 			       ; / (only works on tape)
  2194                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2195                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2196                              <1> ;1:
  2197                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2198                              <1> 			    ; / maximum block # allowed on device
  2199                              <1> 		; jnb short @f
  2200                              <1> 		; bhis	1f / yes, 1f (error)
  2201                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2202                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2203                              <1> 		; mov (sp)+,r1 / return block # to r1
  2204                              <1> 		; inc r1 / bump block # to next consecutive block
  2205                              <1> 		; dec (sp) / "2-1-cold" on stack
  2206                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2207                              <1> ;1:
  2208                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2209                              <1> 	;push	ecx ; **
  2210                              <1> 	;26/04/2013
  2211                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2212 00005DC7 2C03                <1> 	sub	al, 3
  2213                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2214 00005DC9 A2[176F0000]        <1> 	mov	[u.brwdev], al
  2215                              <1> 	; 09/06/2015
  2216 00005DCE 0FB6D8              <1> 	movzx	ebx, al
  2217 00005DD1 8B8B[CE680000]      <1> 	mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2218                              <1> bread_0:
  2219 00005DD7 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2220                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2221                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2222 00005DD8 8B1D[B86E0000]      <1> 	mov	ebx, [u.fofp]
  2223 00005DDE 8B03                <1> 	mov	eax, [ebx]
  2224 00005DE0 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2225                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2226                              <1> 			       ; / block #
  2227 00005DE3 39C8                <1> 	cmp	eax, ecx
  2228                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2229                              <1>        	                     ; / block number allowed
  2230                              <1> 	;jnb	error 	     ; 18/04/2013
  2231                              <1> 		; bhis error10 / yes, error
  2232 00005DE5 720F                <1> 	jb	short bread_1
  2233 00005DE7 C705[186F0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error	
  2233 00005DEF 0000                <1>
  2234 00005DF1 E9B6DDFFFF          <1> 	jmp	error
  2235                              <1> bread_1:
  2236                              <1> 	; inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2237                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2238                              <1> 	; eAX = Block number (zero based)
  2239                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2240                              <1> preread: ;; call preread
  2241 00005DF6 BF[176F0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2242 00005DFB E86A020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2243                              <1> 	;; jc 	error
  2244                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2245                              <1>         ; eAX = Block/Sector number (r1)
  2246                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2247                              <1> 	; 14/03/2013
  2248 00005E00 740A                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2249                              <1>        		; br 1f / branch if block already in a I/O buffer
  2250 00005E02 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2251                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2252 00005E07 E8B3010000          <1> 	call	poke
  2253                              <1>         	; jsr r0,poke / perform the read
  2254                              <1> 	;;jc	error ;2 0/07/2013
  2255                              <1> ; 1:
  2256                              <1>  		; clr *$ps / ps = 0
  2257                              <1>         	; rts r0
  2258                              <1> ;; return from preread
  2259                              <1> bread_2:
  2260 00005E0C 66810B0040          <1> 	or	word [ebx], 4000h 
  2261                              <1> 		; bis $40000,(r5) 
  2262                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2263                              <1> bread_3: ; 1:
  2264 00005E11 66F7030024          <1> 	test	word [ebx], 2400h
  2265                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2266 00005E16 7407                <1> 	jz	short bread_4
  2267                              <1> 		; beq 1f / no
  2268                              <1> 		; cmp cdev,$1 / disk or drum?
  2269                              <1> 		; ble 2f / yes
  2270                              <1> 		; tstb uquant / is the time quantum = 0?
  2271                              <1> 		; bne 2f / no, 2f
  2272                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2273                              <1> 		; jsr r0,sleep; 31. 
  2274                              <1> 			; / put process to sleep in channel 31 (tape)
  2275                              <1> 		; mov (sp)+,r5 / restore r5
  2276                              <1> 		; br 1b / go back
  2277                              <1> ; 2: / drum or disk
  2278                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2279 00005E18 E8D2EFFFFF          <1> 	call	idle
  2280                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2281 00005E1D EBF2                <1> 	jmp	short bread_3
  2282                              <1>        		; br 1b
  2283                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2284 00005E1F 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2285                              <1> 		; bic $40000,(r5) / clear bit 14
  2286                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2287 00005E24 83C308              <1> 	add	ebx, 8
  2288                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2289                              <1> 	; 09/06/2015
  2290 00005E27 66833D[106F0000]00  <1> 	cmp	word [u.pcount], 0
  2291 00005E2F 7705                <1> 	ja	short bread_5
  2292 00005E31 E841F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2293                              <1> bread_5:
  2294                              <1> 	; eBX = system (I/O) buffer address
  2295 00005E36 E870000000          <1> 	call	dioreg
  2296                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2297                              <1> 	; esi =  start address of the transfer (in the buffer)
  2298                              <1> 	; edi =  [u.pbase], destination address in user's memory space
  2299                              <1> 	; ecx =  transfer count (in bytes)
  2300                              <1> 	;
  2301                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2302                              <1> ;   / of users data
  2303 00005E3B F3A4                <1> 	rep	movsb
  2304                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2305                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2306                              <1>        		; bne 1b
  2307 00005E3D 59                  <1> 	pop	ecx ; **
  2308 00005E3E 833D[CC6E0000]00    <1> 	cmp	dword [u.count], 0
  2309                              <1> 		; tst u.count / done
  2310 00005E45 7790                <1> 	ja	short bread_0 ; 09/06/2015
  2311                              <1>        		; beq 1f / yes, return
  2312                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2313                              <1>        		; br bread / read some more
  2314                              <1> ; 1:
  2315 00005E47 58                  <1> 	pop	eax ; ****
  2316                              <1>        		; mov (sp)+,r0
  2317 00005E48 C3                  <1>         retn		; 09/06/2015
  2318                              <1> 	;jmp     ret_ 
  2319                              <1> 		;jmp ret  / jump to routine that called readi
  2320                              <1> 
  2321                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2322                              <1> 	; 26/04/2013
  2323                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2324                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2325                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2326                              <1> 				
  2327                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2328                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2329                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2330                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2331                              <1> 
  2332                              <1> bwrite: 
  2333                              <1> 	; 14/07/2015
  2334                              <1> 	; 10/07/2015
  2335                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2336                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2337                              <1> 	;	
  2338                              <1> 	;; / write on block structured device
  2339                              <1> 	;
  2340                              <1> 	; INPUTS ->
  2341                              <1> 	;    [u.fopf] points to the block number
  2342                              <1> 	;    CX = maximum block number allowed on device
  2343                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2344                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2345                              <1> 	;    [u.count]	number of bytes to user desires to write
  2346                              <1> 	; OUTPUTS ->
  2347                              <1> 	;    [u.fopf] points to next consecutive block to be written into
  2348                              <1> 	;
  2349                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2350                              <1> 	;
  2351                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2352                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2353                              <1> 	;	is increased by 1. For example: If user/program request 
  2354                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2355                              <1> 	;  	the next block number just as 512 byte writing is done.
  2356                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2357                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2358                              <1> 	;       enough to keep byte position/offset of the disk), this
  2359                              <1> 	;	defect will not be corrected, user/program must request
  2360                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2361                              <1> 	;       for achieving correct result. In future version(s), 
  2362                              <1> 	;	this defect will be corrected by using different 
  2363                              <1> 	;       user (u) structure.  26/07/2013 - Erdogan Tan 	
  2364                              <1> 
  2365                              <1>        		; jsr r0,tstdeve / test the device for an error
  2366                              <1> 	;push	ecx ; **
  2367                              <1> 	;26/04/2013
  2368                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2369 00005E49 2C03                <1> 	sub	al, 3
  2370                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2371 00005E4B A2[176F0000]        <1> 	mov	[u.brwdev], al
  2372                              <1> 	; 09/06/2015
  2373 00005E50 0FB6D8              <1> 	movzx	ebx, al
  2374 00005E53 8B8B[CE680000]      <1> 	mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2375                              <1> bwrite_0:
  2376 00005E59 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2377                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2378                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2379 00005E5A 8B1D[B86E0000]      <1> 	mov	ebx, [u.fofp]
  2380 00005E60 8B03                <1> 	mov	eax, [ebx]       
  2381 00005E62 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2382                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2383 00005E65 39C8                <1> 	cmp	eax, ecx
  2384                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2385                              <1>        	                     ; / block number allowed
  2386                              <1> 	;jnb	error	     ; 18/04/2013
  2387                              <1> 		; bhis error10 / yes, error
  2388 00005E67 720F                <1>      	jb	short bwrite_1
  2389 00005E69 C705[186F0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error	
  2389 00005E71 0000                <1>
  2390 00005E73 E934DDFFFF          <1> 	jmp	error
  2391                              <1> bwrite_1:
  2392                              <1> 	; inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2393                              <1> 		; inc *u.fofp / no, increment block number
  2394                              <1> 	; 09/06/2015 - 10/07/2015
  2395 00005E78 66833D[106F0000]00  <1> 	cmp	word [u.pcount], 0
  2396 00005E80 7705                <1> 	ja	short bwrite_2
  2397 00005E82 E8ECF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2398                              <1> bwrite_2:
  2399 00005E87 BF[176F0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2400 00005E8C E8C4000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2401                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2402                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2403 00005E91 E815000000          <1>         call	dioreg
  2404                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2405                              <1> 	; esi =  destination address (in the buffer)
  2406                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2407                              <1> 	; ecx =  transfer count (in bytes)
  2408                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2409 00005E96 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2410 00005E98 F3A4                <1> 	rep	movsb
  2411                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2412                              <1>        		; dec r3 / area to the I/O buffer
  2413                              <1>        		; bne 1b
  2414 00005E9A E8FE000000          <1> 	call	dskwr
  2415                              <1> 		; jsr r0,dskwr / write it out on the device
  2416 00005E9F 59                  <1> 	pop	ecx ; **
  2417 00005EA0 833D[CC6E0000]00    <1>         cmp     dword [u.count], 0
  2418                              <1> 		; tst u.count / done
  2419 00005EA7 77B0                <1> 	ja	short bwrite_0 ; 09/06/2015
  2420                              <1> 		; beq 1f / yes, 1f
  2421                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2422                              <1>        		; br bwrite / go back and write next block
  2423                              <1> ; 1:
  2424 00005EA9 58                  <1> 	pop	eax ; ****
  2425                              <1>        		; mov (sp)+,r0
  2426 00005EAA C3                  <1> 	retn		; 09/06/2015
  2427                              <1>         ;jmp     ret_ 
  2428                              <1> 		; jmp ret / return to routine that called writei
  2429                              <1> ;error10:
  2430                              <1> ;       jmp     error  ; / see 'error' routine
  2431                              <1> 
  2432                              <1> dioreg:
  2433                              <1> 	; 14/07/2015
  2434                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2435                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2436                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2437                              <1> 	;	
  2438                              <1> 	; bookkeeping on block transfers of data
  2439                              <1> 	;
  2440                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2441                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2442                              <1> 	; 10/07/2015
  2443                              <1> 	; * returns byte offset from beginning of current sector buffer
  2444                              <1> 	; (beginning of data) in ESI
  2445                              <1> 	;
  2446 00005EAB 8B0D[CC6E0000]      <1> 	mov	ecx, [u.count]
  2447                              <1> 		; mov u.count,r3 / move char count to r3
  2448 00005EB1 81F900020000        <1>        	cmp 	ecx, 512
  2449                              <1> 		; cmp r3,$512. / more than 512. char?
  2450 00005EB7 7605                <1> 	jna	short dioreg_0
  2451                              <1> 		; blos 1f / no, branch
  2452 00005EB9 B900020000          <1> 	mov	ecx, 512
  2453                              <1> 		; mov $512.,r3 / yes, just take 512.
  2454                              <1> dioreg_0:
  2455                              <1> 	; 09/06/2015
  2456 00005EBE 663B0D[106F0000]    <1> 	cmp	cx, [u.pcount]
  2457 00005EC5 7607                <1> 	jna	short dioreg_1
  2458 00005EC7 668B0D[106F0000]    <1> 	mov	cx, [u.pcount]
  2459                              <1> dioreg_1:
  2460                              <1> ; 1:
  2461 00005ECE 8B15[C86E0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2462                              <1> 	        ; mov u.base,r2 / put users base in r2
  2463 00005ED4 010D[D06E0000]      <1> 	add	[u.nread], ecx
  2464                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2465 00005EDA 290D[CC6E0000]      <1> 	sub	[u.count], ecx
  2466                              <1> 		; sub r3,u.count / update count
  2467 00005EE0 010D[C86E0000]      <1> 	add	[u.base], ecx
  2468                              <1> 		; add r3,u.base / update base
  2469                              <1> 	; 10/07/2015
  2470                              <1> 	; Retro UNIX 386 v1 - modification !
  2471                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2472                              <1> 	; (It will point to next byte position instead of next block no.)
  2473 00005EE6 8B35[B86E0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2474 00005EEC 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2475 00005EEE 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2476 00005EF0 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2477 00005EF5 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2478 00005EF7 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2479                              <1> 	; 09/06/2015 - 10/07/2015
  2480 00005EF9 66290D[106F0000]    <1> 	sub	[u.pcount], cx
  2481 00005F00 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2482 00005F06 8B3D[0C6F0000]      <1> 	mov	edi, [u.pbase]
  2483 00005F0C 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2484 00005F12 01D7                <1> 	add	edi, edx
  2485 00005F14 893D[0C6F0000]      <1> 	mov	[u.pbase], edi
  2486 00005F1A 010D[0C6F0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2487 00005F20 C3                  <1> 	retn
  2488                              <1> 		; rts r0 / return
  2489                              <1> 
  2490                              <1> dskrd:
  2491                              <1> 	; 18/08/2015
  2492                              <1> 	; 02/07/2015
  2493                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2494                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2495                              <1> 	;
  2496                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2497                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2498                              <1> 	; (number specified in r1) in the acquired buffer.)
  2499                              <1> 	; If the device is busy at the time dskrd is called,	
  2500                              <1> 	; dskrd calls idle.
  2501                              <1> 	; 
  2502                              <1> 	; INPUTS ->
  2503                              <1> 	;    r1 - block number
  2504                              <1> 	;    cdev - current device number 
  2505                              <1> 	; OUTPUTS ->
  2506                              <1> 	;    r5 - points to first data word in I/O buffer
  2507                              <1> 	;
  2508                              <1> 	; ((AX = R1)) input/output
  2509                              <1> 	; ((BX = R5)) output 
  2510                              <1> 	;
  2511                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2512                              <1> 	;
  2513 00005F21 E837010000          <1> 	call 	bufaloc
  2514                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2515                              <1> 			       ; / get a free I/O buffer
  2516                              <1> 	;;jc	error ; 20/07/2013
  2517 00005F26 741B                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2518                              <1>        		; br 1f / branch if block already in a I/O buffer
  2519                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2520 00005F28 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2521                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2522                              <1> 		               ; / I/O queue entry for buffer
  2523 00005F2D E88D000000          <1> 	call	poke
  2524                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2525                              <1> 			    ; /	bit 10=1 says read
  2526                              <1> 	; 09/06/2015
  2527 00005F32 730F                <1> 	jnc	short dskrd_1
  2528                              <1> 	;
  2529 00005F34 C705[186F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2529 00005F3C 0000                <1>
  2530 00005F3E E969DCFFFF          <1> 	jmp	error
  2531                              <1> dskrd_1: ; 1:
  2532                              <1>        		;clr *$ps
  2533 00005F43 66F7030024          <1>        	test	word [ebx], 2400h
  2534                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2535                              <1> 				; / jump to idle
  2536 00005F48 7407                <1>        	jz	short dskrd_2
  2537                              <1> 		; beq 1f
  2538                              <1>         ;;mov   ecx, [s.wait_]
  2539 00005F4A E8A0EEFFFF          <1>        	call	idle
  2540                              <1> 		; jsr r0,idle; s.wait+2
  2541 00005F4F EBF2                <1> 	jmp 	short dskrd_1
  2542                              <1>        		; br 1b
  2543                              <1> dskrd_2: ; 1:
  2544 00005F51 83C308              <1>         add	ebx, 8
  2545                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2546                              <1> 			  ; / just read in
  2547 00005F54 C3                  <1>        	retn
  2548                              <1> 		; rts r0
  2549                              <1> 
  2550                              <1> bwslot:
  2551                              <1> 	; 10/07/2015
  2552                              <1> 	;	If the block/sector is not placed in a buffer
  2553                              <1> 	;	before 'wslot', it must be read before
  2554                              <1> 	;	it is written! (Otherwise transfer counts less
  2555                              <1> 	;	than 512 bytes will be able to destroy existing 
  2556                              <1> 	;	data on disk.)
  2557                              <1> 	;
  2558                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2559                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2560                              <1> 	; Retro UNIX 8086 v1 modification !
  2561                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2562                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2563                              <1> 	;	-> eAX = block number
  2564                              <1> 	;
  2565 00005F55 E810010000          <1> 	call	bufaloc_0
  2566 00005F5A 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2567                              <1> bwslot_0:
  2568                              <1> 	; 10/07/2015
  2569 00005F5C 8B35[B86E0000]      <1> 	mov	esi, [u.fofp]
  2570 00005F62 8B06                <1> 	mov	eax, [esi]
  2571 00005F64 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2572 00005F69 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2573                              <1> 		       ; recent disk data must be placed in the buffer
  2574 00005F6B 813D[CC6E0000]0002- <1> 	cmp	dword [u.count], 512
  2574 00005F73 0000                <1>
  2575 00005F75 730F                <1> 	jnb	short wslot_0	
  2576                              <1> bwslot_1:
  2577 00005F77 E8ACFFFFFF          <1> 	call	dskrd_0
  2578 00005F7C 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again	
  2579 00005F7F EB05                <1> 	jmp 	short wslot_0
  2580                              <1> 
  2581                              <1> wslot:
  2582                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2583                              <1> 	; 		(32 bit modifications)
  2584                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2585                              <1> 	;
  2586                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2587                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2588                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2589                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2590                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2591                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2592                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2593                              <1> 	;
  2594                              <1> 	; INPUTS ->
  2595                              <1>  	;    r1 - block number
  2596                              <1> 	;    cdev - current (block/disk) device number
  2597                              <1>  	;
  2598                              <1> 	; OUTPUTS ->
  2599                              <1> 	;    bufp - bits 9 and 15 are set, 
  2600                              <1> 	;           the remainder of the word left unchanged
  2601                              <1> 	;    r5 - points to first data word in I/O buffer
  2602                              <1> 	;
  2603                              <1> 	; ((AX = R1)) input/output
  2604                              <1> 	; ((BX = R5)) output 
  2605                              <1> 	;
  2606                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2607                              <1> 
  2608 00005F81 E8D7000000          <1> 	call	bufaloc
  2609                              <1> 	; 10/07/2015
  2610                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2611                              <1>         	; br 1f / word in buffer in r5
  2612                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2613                              <1>         ; eAX = Block/Sector number (r1)
  2614                              <1> wslot_0: ;1:
  2615 00005F86 66F7030024          <1>      	test	word [ebx], 2400h
  2616                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2617                              <1> 				; / of I/O queue entry
  2618 00005F8B 7407                <1> 	jz	short wslot_1
  2619                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2620                              <1> 		     ; / or not waiting to read)
  2621                              <1> 
  2622                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2623 00005F8D E85DEEFFFF          <1> 	call	idle
  2624                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2625                              <1>        	                     ; / idle
  2626 00005F92 EBF2                <1> 	jmp	short wslot_0
  2627                              <1> 		; br 1b / till finished
  2628                              <1> wslot_1: ;1:
  2629 00005F94 66810B0082          <1>         or      word [ebx], 8200h
  2630                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2631                              <1>                             	 ; / (write, inhibit bits)
  2632                              <1>        		; clr     *$ps / clear processor status
  2633 00005F99 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2634                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2635                              <1> 			  ; / for this block
  2636 00005F9C C3                  <1>        	retn
  2637                              <1> 		; rts r0
  2638                              <1> dskwr:
  2639                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2640                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2641                              <1> 	;
  2642                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2643                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2644                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2645                              <1> 	; previously has supplied all the information required in the
  2646                              <1> 	; I/O queue entry.
  2647                              <1> 	;
  2648                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2649                              <1> 	;
  2650                              <1> 	;
  2651 00005F9D 8B1D[606E0000]      <1> 	mov	ebx, [bufp]
  2652 00005FA3 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2653                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2654                              <1>                                   ; / bottom of queue
  2655 00005FA8 E812000000          <1> 	call	poke
  2656                              <1> 	; 09/06/2015
  2657 00005FAD 730F                <1> 	jnc	short dskwr_1
  2658 00005FAF C705[186F0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2658 00005FB7 0000                <1>
  2659 00005FB9 E9EEDBFFFF          <1> 	jmp	error
  2660                              <1> dskwr_1:
  2661 00005FBE C3                  <1> 	retn
  2662                              <1> 
  2663                              <1> ;ppoke:
  2664                              <1>        		; mov $340,*$ps
  2665                              <1>        		; jsr r0,poke
  2666                              <1>        		; clr *$ps
  2667                              <1> 		; rts r0
  2668                              <1> poke:
  2669                              <1> 	; 29/11/2021 (32 bit reg push-pop)
  2670                              <1> 	; 24/10/2015
  2671                              <1> 	; 20/08/2015
  2672                              <1> 	; 18/08/2015
  2673                              <1> 	; 02/07/2015
  2674                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2675                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2676                              <1> 	;
  2677                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2678                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2679                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2680                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2681                              <1> 	;
  2682                              <1> 	; Basic I/O functions for all block structured devices
  2683                              <1> 	;
  2684                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2685                              <1> 	;
  2686                              <1> 	; 20/07/2013 modifications
  2687                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2688                              <1> 	; INPUTS -> 
  2689                              <1> 	;        (EBX = buffer header address)
  2690                              <1> 	; OUTPUTS ->
  2691                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2692                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2693                              <1> 	;		(drive not ready or r/w error!)
  2694                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2695                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2696                              <1> 	;        (also it indicates invalid buffer data)
  2697                              <1> 	;
  2698 00005FBF 53                  <1> 	push	ebx
  2699                              <1>        		; mov r1,-(sp)
  2700                              <1>        		; mov r2,-(sp)
  2701                              <1>        		; mov r3,-(sp)
  2702 00005FC0 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2703                              <1> 	;
  2704                              <1> 	; 09/06/2015
  2705                              <1> 	; (permit read/write after a disk R/W error)
  2706 00005FC1 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2707 00005FC3 B001                <1> 	mov	al, 1
  2708 00005FC5 D2E0                <1> 	shl	al, cl
  2709 00005FC7 8405[886E0000]      <1> 	test 	al, [active] ; busy ? (error)
  2710 00005FCD 7408                <1> 	jz	short poke_0
  2711 00005FCF F6D0                <1> 	not	al
  2712 00005FD1 2005[886E0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2713                              <1> poke_0:
  2714 00005FD7 BE[806E0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2715                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2716                              <1> 					 ; / I/O queue pointer
  2717                              <1> poke_1: ; 1:
  2718 00005FDC 83EE04              <1>         sub	esi, 4
  2719 00005FDF 8B1E                <1> 	mov	ebx, [esi]
  2720                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2721 00005FE1 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2722 00005FE4 F6C406              <1>        	test	ah, 06h
  2723                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2724                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2725                              <1> 			       ; / queue entry
  2726 00005FE7 745C                <1>         jz      short poke_5
  2727                              <1> 		; beq 2f / branch to 2f if both are clear
  2728                              <1> 	; 31/07/2013
  2729                              <1> 	;test	ah, 0B0h ; (*)
  2730                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2731                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2732                              <1>         ;jnz     short poke_5 ; 31/07/2013 (*)
  2733                              <1> 		; bne 2f / branch if any are set
  2734                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2735                              <1>     		; movb (r1),r3 / get device id
  2736 00005FE9 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2737                              <1> 	;mov	edi, ecx ; 26/04/2013
  2738 00005FEC 31C0                <1> 	xor 	eax, eax ; 0
  2739                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2740                              <1> 		; tstb deverr(r3) / test for errors on this device
  2741                              <1>        	;jna	short poke_2 
  2742                              <1> 		; beq 3f / branch if no errors
  2743                              <1> 	; 02/07/2015
  2744                              <1> 	;dec	eax
  2745                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2746                              <1>        		; mov $-1,2(r1) / destroy associativity
  2747                              <1> 	;shr	eax, 24
  2748                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2749                              <1> 		; clrb 1(r1) / do not do I/O
  2750                              <1> 	;jmp     short poke_5
  2751                              <1>         ;       ; br 2f
  2752                              <1>                 ; rts r0
  2753                              <1> poke_2: ; 3:
  2754                              <1> 	; 02/07/2015
  2755 00005FEE FEC1                <1> 	inc	cl ; 0FFh -> 0
  2756 00005FF0 7453                <1> 	jz	short poke_5
  2757 00005FF2 FEC0                <1> 	inc	al ; mov ax, 1
  2758 00005FF4 FEC9                <1> 	dec	cl
  2759 00005FF6 7402                <1> 	jz	short poke_3
  2760                              <1> 	; 26/04/2013 Modification
  2761                              <1> 	;inc	al ; mov ax, 1
  2762                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2763                              <1> 	;jz	short poke_3 ; cl = 0
  2764 00005FF8 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2765                              <1> poke_3:
  2766                              <1> 	;test	[active], ax
  2767 00005FFA 8405[886E0000]      <1> 	test	[active], al
  2768                              <1> 		; bit $2,active / test disk busy bit
  2769 00006000 7543                <1> 	jnz     short poke_5
  2770                              <1> 		; bne 2f / branch if bit is set
  2771                              <1> 	;or	[active], ax
  2772 00006002 0805[886E0000]      <1> 	or	[active], al
  2773                              <1> 		; bis $2,active / set disk busy bit
  2774 00006008 50                  <1> 	push	eax ; 29/11/2021
  2775 00006009 E8D2000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2776                              <1> 	;mov    [edi+drv.error], ah
  2777 0000600E 58                  <1> 	pop	eax
  2778 0000600F 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2779                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2780                              <1> 	;jna	short poke_4
  2781                              <1> 		; tstb deverr(r3) / test for errors on this device
  2782                              <1>        		; beq 3f / branch if no errors
  2783                              <1> 	; 02/07/2015 (32 bit modification)
  2784                              <1> 	; 20/07/2013
  2785 00006011 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2786                              <1>        		; mov $-1,2(r1) / destroy associativity
  2787 00006018 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2788                              <1> 		; clrb 1(r1) / do not do I/O
  2789 0000601D EB26                <1> 	jmp     short poke_5
  2790                              <1> poke_4:	; 20/07/2013
  2791                              <1> 	; 17/07/2013
  2792 0000601F F6D0                <1> 	not 	al 
  2793 00006021 2005[886E0000]      <1> 	and	[active], al ; reset, not busy
  2794                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2795                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2796 00006027 668B03              <1> 	mov	ax, [ebx]
  2797                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2798 0000602A 66250006            <1>         and	ax, 600h
  2799                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2800 0000602E 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2801                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2802 00006033 C0E403              <1> 	shl	ah, 3
  2803                              <1>        		; rol r3
  2804                              <1>                 ; rol r3
  2805                              <1>                 ; rol r3	
  2806 00006036 660903              <1> 	or	[ebx], ax
  2807                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2808                              <1> 			   ; bits 12 and 13
  2809 00006039 E8B1EDFFFF          <1> 	call	idle ; 18/01/2014
  2810                              <1> 	;; sti
  2811                              <1> 	;hlt 	; wait for a hardware interrupt
  2812                              <1> 	;; cli
  2813                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2814                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2815                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2816                              <1> 	; method, this procedure will wait for a time according to
  2817                              <1> 	; multi tasking and time sharing concept.
  2818                              <1> 	;
  2819                              <1> 	; 24/10/2015
  2820                              <1> 	;not	ax 
  2821 0000603E 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2822 00006042 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2823                              <1> poke_5: ;2:
  2824 00006045 81FE[606E0000]      <1>         cmp     esi, bufp
  2825                              <1> 		; cmp r2,$bufp / test to see if entire I/O queue 
  2826                              <1>                             ; / has been scanned
  2827 0000604B 778F                <1> 	ja      short poke_1
  2828                              <1> 		; bhi 1b
  2829                              <1> 	; 24/03/2013
  2830                              <1>        		; mov (sp)+,r3
  2831                              <1>        		; mov (sp)+,r2
  2832                              <1>        		; mov (sp)+,r1
  2833 0000604D 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2834 0000604E 5B                  <1> 	pop 	ebx
  2835                              <1> 	; 02/07/2015 (32 bit modification)
  2836                              <1> 	; 20/07/2013
  2837                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2838 0000604F 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2839                              <1> 	;	
  2840                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2841                              <1> 	; or written succesfully; even if an error occurs while
  2842                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2843                              <1> 	;
  2844                              <1> 	; 09/06/2015
  2845 00006052 F5                  <1> 	cmc
  2846 00006053 C3                  <1> 	retn
  2847                              <1>                 ; rts r0
  2848                              <1> 
  2849                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatibility code
  2850                              <1> get_system_time:
  2851                              <1> 	; 27/10/2021
  2852                              <1> 	; 21/02/2020 - Retro UNIX 386 v2
  2853                              <1> 	; get system time
  2854                              <1> 	;  (from recent value which is saved in RTC interrupt)
  2855                              <1> 	; Input:
  2856                              <1> 	; 	none
  2857                              <1> 	; Return:
  2858                              <1> 	;   	eax = system time in unix epoch format 
  2859                              <1> 	;
  2860                              <1> 	; Modified registers: eax, ecx, edx
  2861                              <1> 	
  2862                              <1> 	; 27/11/2021
  2863 00006054 53                  <1> 	push	ebx
  2864 00006055 E86FD6FFFF          <1> 	call	epoch
  2865 0000605A 5B                  <1> 	pop	ebx
  2866 0000605B C3                  <1> 	retn
  2867                              <1> 
  2868                              <1> get_serial_number:
  2869                              <1> 	; temporary - 21/02/2020
  2870                              <1> 	; 26/04/2020 (esi)
  2871                              <1> 	; 25/04/2020
  2872                              <1> 	; (Possible) Modified registers: eax, ecx, edx
  2873                              <1> 	; (edi, ebx & esi registers must be preserved)
  2874                              <1> 	; Return:
  2875                              <1> 	; eax = 32 bit serial number  
  2876                              <1> 	; (edx = high 32 bit of 64 bit serial number)
  2877                              <1> 	; -64 bit serial numbers will not be used in RUNIX 386 v2-
  2878 0000605C C3                  <1> 	retn
  2879                              <1> 
  2880                              <1> bufaloc:
  2881                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  2882                              <1> 	; 20/08/2015
  2883                              <1> 	; 19/08/2015
  2884                              <1> 	; 02/07/2015
  2885                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2886                              <1> 	;	     (32 bit modifications)	
  2887                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2888                              <1> 	;
  2889                              <1> 	; bufaloc - Block device I/O buffer allocation
  2890                              <1> 	; 
  2891                              <1> 	; INPUTS ->
  2892                              <1> 	;    r1 - block number
  2893                              <1> 	;    cdev - current (block/disk) device number
  2894                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2895                              <1> 	; OUTPUTS ->
  2896                              <1> 	;    r5 - pointer to buffer allocated
  2897                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2898                              <1> 	;
  2899                              <1> 	; ((AX = R1)) input/output
  2900                              <1> 	; ((BX = R5)) output
  2901                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2902                              <1> 	;    zf=1 -> block already in a I/O buffer
  2903                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2904                              <1> 	;    ((DL = Device ID))
  2905                              <1> 	;    (((DH = 0 or 1)))
  2906                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2907                              <1> 	;    ((CX and DH will not be used after return)))
  2908                              <1> 
  2909                              <1> 	;;push 	esi ; ***
  2910                              <1> 		; mov r2,-(sp) / save r2 on stack
  2911                              <1>        		; mov $340,*$ps / set processor priority to 7
  2912                              <1> 	; 20/07/2013
  2913                              <1> 	; 26/04/2013
  2914                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2915                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  2916                              <1> 	;add	edi, ebx
  2917                              <1> 	; 09/01/2022
  2918 0000605D 0FB63D[856E0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2919 00006064 81C7[866E0000]      <1> 	add	edi, rdev
  2920                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2921                              <1> 			;; eDI points to device id.
  2922 0000606A 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2923                              <1> 	; 11/06/2021
  2924 0000606D 80BB[EA680000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2925 00006074 720F                <1> 	jb	short bufaloc_9
  2926 00006076 C705[186F0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2926 0000607E 0000                <1>
  2927 00006080 E927DBFFFF          <1> 	jmp	error
  2928                              <1> bufaloc_9:
  2929 00006085 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2930                              <1> bufaloc_10: ; 02/07/2015
  2931 00006087 31ED                <1> 	xor 	ebp, ebp ; 0
  2932 00006089 55                  <1> 	push	ebp ; 0
  2933 0000608A 89E5                <1>         mov     ebp, esp	
  2934                              <1> 	;
  2935                              <1> bufaloc_1: ;1:
  2936                              <1> 		; clr -(sp) / vacant buffer
  2937 0000608C BE[606E0000]        <1>         mov 	esi, bufp
  2938                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2939                              <1> 			     ; / entrys in buffer area
  2940                              <1> bufaloc_2: ;2:
  2941 00006091 8B1E                <1> 	mov	ebx, [esi]
  2942                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2943                              <1> 			    ; queue entry into r5
  2944 00006093 66F70300F6          <1> 	test	word [ebx], 0F600h
  2945                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2946 00006098 7503                <1>         jnz	short bufaloc_3
  2947                              <1> 		; bne 3f / branch when 
  2948                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2949                              <1>                        ; / (i.e., buffer busy)
  2950 0000609A 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2951                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2952                              <1> 			; / found points to word 2 of I/O queue entry)
  2953                              <1> bufaloc_3: ;3:
  2954                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2955                              <1> 	;
  2956 0000609D 3813                <1> 	cmp	[ebx], dl	
  2957                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2958                              <1> 			       ; / as current device
  2959 0000609F 7508                <1> 	jne	short bufaloc_4
  2960                              <1>        		; bne 3f
  2961 000060A1 394304              <1> 	cmp	[ebx+4], eax
  2962                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2963                              <1> 			     ; / same as current block number
  2964 000060A4 7503                <1>        	jne	short bufaloc_4
  2965                              <1> 		; bne 3f
  2966                              <1> 	;add	esp, 4
  2967 000060A6 59                  <1> 	pop	ecx
  2968                              <1>        		; tst (sp)+ / bump stack pointer
  2969 000060A7 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2970                              <1> 				; jump to bufaloc_6 in original Unix v1
  2971                              <1>        		; br 1f / use this buffer
  2972                              <1> bufaloc_4: ;3:
  2973 000060A9 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2974                              <1> 	;
  2975 000060AC 81FE[786E0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2976                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2977 000060B2 72DD                <1> 	jb	short bufaloc_2
  2978                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2979                              <1>                        ; / buffers not checked)
  2980 000060B4 5E                  <1>         pop	esi
  2981                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2982                              <1> 			     ; / to last free block
  2983 000060B5 09F6                <1>        	or	esi, esi 
  2984 000060B7 7507                <1> 	jnz	short bufaloc_5
  2985                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2986                              <1> 	        ; / if a free buffer is found branch to 2f
  2987                              <1>         ;; mov  ecx, [s.wait_]
  2988 000060B9 E831EDFFFF          <1> 	call	idle
  2989                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2990 000060BE EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  2991                              <1>        		; br 1b
  2992                              <1> bufaloc_5: ;2:
  2993                              <1> 		; tst (r0)+ / skip if warmed over buffer
  2994 000060C0 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  2995                              <1> bufaloc_6: ;1:
  2996 000060C2 8B1E                <1>         mov    	ebx, [esi] 
  2997                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  2998                              <1> 			     ; / entry in r5
  2999                              <1> 	;; 26/04/2013
  3000                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3001 000060C4 8813                <1> 	mov 	[ebx], dl
  3002                              <1> 		; movb cdev,(r5) / put current device number 
  3003                              <1> 				 ; / in I/O queue entry
  3004 000060C6 894304              <1> 	mov 	[ebx+4], eax
  3005                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3006                              <1> 			     ; / of I/O queue entry
  3007                              <1> bufaloc_7: ;1:
  3008 000060C9 81FE[606E0000]      <1>         cmp	esi, bufp
  3009                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3010                              <1> 			     ; / and put latest assigned
  3011 000060CF 760A                <1> 	jna	short bufaloc_8	
  3012                              <1>        		; blos 1f / buffer on the top 
  3013                              <1> 			; / (this makes if the lowest priority)
  3014 000060D1 83EE04              <1> 	sub	esi, 4
  3015 000060D4 8B0E                <1> 	mov	ecx, [esi]
  3016 000060D6 894E04              <1> 	mov	[esi+4], ecx
  3017                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3018 000060D9 EBEE                <1> 	jmp 	short bufaloc_7        
  3019                              <1> 		; br 1b
  3020                              <1> bufaloc_8: ;1:
  3021 000060DB 891E                <1>         mov	[esi], ebx
  3022                              <1> 		; mov r5,(r2)
  3023                              <1> 	;;pop	esi ; ***
  3024                              <1>        		; mov (sp)+,r2 / restore r2
  3025 000060DD 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3026                              <1> 		; Retro UNIX 8086 v1 modification
  3027                              <1> 		; zf=1 --> block already is in an I/O buffer
  3028                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3029 000060DF C3                  <1> 	retn
  3030                              <1> 		; rts r0
  3031                              <1> 
  3032                              <1> diskio:
  3033                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.2)
  3034                              <1> 	; 28/11/2021
  3035                              <1> 	; 10/07/2015
  3036                              <1> 	; 02/07/2015
  3037                              <1> 	; 16/06/2015
  3038                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3039                              <1> 	;	     (80386 protected mode modifications)	
  3040                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3041                              <1> 	;
  3042                              <1> 	; Retro UNIX 8086 v1 feature only !
  3043                              <1> 	;
  3044                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3045                              <1> 	; 04/07/2009 - 20/07/2011
  3046                              <1> 	;
  3047                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3048                              <1> 	;
  3049                              <1>         ; INPUTS ->
  3050                              <1> 	; 	   ebx = System I/O Buffer header address
  3051                              <1> 	;
  3052                              <1>         ; OUTPUTS -> cf=0 --> done 
  3053                              <1> 	; 	     cf=1 ---> error code in AH
  3054                              <1> 	;
  3055                              <1> 	; (Modified registers: eax, ecx, edx)
  3056                              <1> 	
  3057                              <1> ;rw_disk_sector:
  3058                              <1> 	; 28/11/2021
  3059                              <1> 	; 10/07/2015
  3060                              <1> 	; 02/07/2015
  3061                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3062                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3063                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3064                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3065                              <1> 	;
  3066                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3067 000060E0 B602                <1> 	mov	dh, 2
  3068                              <1> 	;mov	ax, [ebx]
  3069                              <1> 	; 28/11/2021
  3070 000060E2 8B03                <1> 	mov	eax, [ebx]
  3071                              <1> 	;
  3072 000060E4 56                  <1> 	push	esi ; ****
  3073 000060E5 53                  <1> 	push	ebx ; ***
  3074                              <1> 	;
  3075 000060E6 0FB6C8              <1> 	movzx	ecx, al
  3076                              <1> 	; 28/11/2021
  3077                              <1> 	;mov	ecx, eax
  3078 000060E9 89CE                <1> 	mov	esi, ecx
  3079                              <1> 	;
  3080 000060EB 38F1                <1> 	cmp	cl, dh ; 2
  3081 000060ED 7202                <1> 	jb	short rwdsk0
  3082 000060EF 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3083                              <1> rwdsk0:
  3084 000060F1 A2[9B680000]        <1> 	mov	[drv], al
  3085 000060F6 81C6[EA680000]      <1> 	add	esi, drv.status
  3086                              <1> 	; 11/06/2015
  3087 000060FC 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3088 000060FF 720F                <1> 	jb      short rwdsk1
  3089                              <1> 	; 'drive not ready' error
  3090 00006101 C705[186F0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3090 00006109 0000                <1>
  3091 0000610B E99CDAFFFF          <1> 	jmp	error
  3092                              <1> rwdsk1:
  3093 00006110 F6C402              <1> 	test	ah, 2
  3094                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3095                              <1> 			 ; write bit
  3096 00006113 7402                <1> 	jz	short rwdsk2
  3097                              <1> 	;test	ah, 4
  3098                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3099                              <1> 	;		 ; read bit
  3100                              <1> 	;jz	short diskio_ret
  3101 00006115 FEC6                <1> 	inc	dh ; 03h = write
  3102                              <1> rwdsk2:
  3103 00006117 88C2                <1> 	mov	dl, al
  3104 00006119 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3105 0000611C 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3106 0000611E C0E102              <1> 	shl	cl, 2
  3107 00006121 81C1[CE680000]      <1> 	add	ecx, drv.size ; disk size
  3108 00006127 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3109 00006129 720F                <1> 	jb      short rwdsk3
  3110                              <1>  	; 'out of volume' error
  3111 0000612B C705[186F0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3111 00006133 0000                <1>
  3112 00006135 E972DAFFFF          <1> 	jmp	error
  3113                              <1> rwdsk3:
  3114                              <1> 	; 11/06/2015
  3115 0000613A 83C304              <1> 	add	ebx, 4 ; buffer address
  3116 0000613D C605[3B6F0000]04    <1> 	mov	byte [retry_count], 4
  3117 00006144 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3118 00006147 7432                <1>         jz      short rwdsk_chs
  3119                              <1> rwdsk_lba:
  3120                              <1> 	; LBA read/write (with private LBA function) 
  3121                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3122 00006149 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3123 0000614C 89C1                <1> 	mov	ecx, eax ; sector number
  3124                              <1> 	; ebx = buffer (data) address
  3125                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3126                              <1> rwdsk_lba_retry:
  3127                              <1> 	;mov	dl, [drv]
  3128                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3129 0000614E B419                <1> 	mov	ah, 1Ch - 03h ; LBA write function number - 3
  3130 00006150 00F4                <1> 	add	ah, dh		
  3131 00006152 B001                <1> 	mov	al, 1
  3132                              <1> 	;int	13h
  3133 00006154 E8F5C4FFFF          <1> 	call	int13h
  3134 00006159 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3135 0000615B 730E                <1> 	jnc	short rwdsk_lba_ok
  3136 0000615D 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3137 00006160 7408                <1>         je      short rwdsk_lba_fails
  3138 00006162 FE0D[3B6F0000]      <1> 	dec	byte [retry_count]
  3139 00006168 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3140                              <1> rwdsk_lba_fails:
  3141 0000616A F9                  <1> 	stc
  3142                              <1> rwdsk_lba_ok:
  3143 0000616B 5B                  <1> 	pop	ebx ; ***
  3144 0000616C 5E                  <1> 	pop	esi ; ****
  3145 0000616D C3                  <1> 	retn
  3146                              <1> rwdsk_lba_reset:
  3147 0000616E B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3148                              <1> 	;int	13h
  3149 00006170 E8D9C4FFFF          <1>         call	int13h
  3150 00006175 73D7                <1> 	jnc     short rwdsk_lba_retry
  3151 00006177 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3152 00006179 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3153                              <1> 	;
  3154                              <1> 	; CHS read (convert LBA address to CHS values)	
  3155                              <1> rwdsk_chs:
  3156                              <1> 	; 10/07/2015
  3157 0000617B 81EE[EA680000]      <1> 	sub	esi, drv.status
  3158 00006181 89F1                <1> 	mov	ecx, esi
  3159 00006183 81C6[F1680000]      <1> 	add 	esi, drv.error
  3160                              <1> 	; 02/07/2015
  3161                              <1> 	; 16/06/2015
  3162                              <1>  	; 11/06/2015 
  3163 00006189 53                  <1> 	push	ebx ; ** ; buffer
  3164 0000618A D1E1                <1> 	shl	ecx, 1
  3165 0000618C 51                  <1> 	push	ecx ; * 
  3166                              <1> 	;
  3167 0000618D 89CB                <1> 	mov	ebx, ecx
  3168 0000618F 8835[396F0000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3169 00006195 31D2                <1> 	xor	edx, edx ; 0
  3170                              <1> 	; 09/01/2022
  3171                              <1> 	;sub	ecx, ecx 
  3172 00006197 81C3[C0680000]      <1>         add     ebx, drv.spt
  3173 0000619D 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3174                              <1> 		; EDX:EAX = LBA
  3175                              <1> ; 28/11/2021 - temporary
  3176 000061A0 09C9                <1> or ecx, ecx
  3177 000061A2 7515                <1> jnz short bunugec1
  3178 000061A4 50                  <1> push	eax
  3179 000061A5 B44E                <1> mov	ah, 4Eh
  3180 000061A7 B021                <1> mov	al, '!'
  3181 000061A9 66A300800B00        <1> mov	[0B8000h], ax
  3182 000061AF B9FFFFFF0F          <1> mov	ecx, 0FFFFFFFh
  3183                              <1> above4:
  3184 000061B4 4A                  <1> dec	edx
  3185 000061B5 42                  <1> inc	edx
  3186 000061B6 E2FC                <1> loop	above4
  3187 000061B8 58                  <1> pop	eax
  3188                              <1> 
  3189                              <1> bunugec1: 
  3190                              <1> 
  3191 000061B9 F7F1                <1> 	div	ecx
  3192 000061BB 88D1                <1> 	mov	cl, dl	; sector number - 1
  3193 000061BD FEC1                <1> 	inc	cl	; sector number (1 based)
  3194 000061BF 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3195                              <1> 	;push	cx
  3196 000061C0 51                  <1> 	push	ecx ; 28/11/2021
  3197 000061C1 81C3[B2680000]      <1>         add     ebx, drv.heads
  3198 000061C7 668B0B              <1> 	mov	cx, [ebx] ; heads
  3199 000061CA 31D2                <1> 	xor	edx, edx
  3200                              <1> 		; EAX = cylinders * heads + head
  3201 000061CC F7F1                <1> 	div	ecx
  3202                              <1> 	;pop	cx     ; sector number
  3203 000061CE 59                  <1> 	pop	ecx ; 28/11/2021
  3204 000061CF 88D6                <1> 	mov	dh, dl ; head number
  3205 000061D1 8A15[9B680000]      <1> 	mov	dl, [drv]
  3206 000061D7 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3207 000061D9 C0E406              <1> 	shl	ah, 6
  3208 000061DC 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3209                              <1> 		       ; sector (bits 0-7)
  3210 000061DE 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3211                              <1> 		; CL = sector (bits 0-5)
  3212                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3213                              <1> 		; CH = cylinder (bits 0-7)
  3214                              <1> 		; DH = head
  3215                              <1> 		; DL = drive
  3216                              <1> 	;
  3217 000061DF C605[3B6F0000]04    <1> 	mov	byte [retry_count], 4
  3218                              <1> rwdsk_retry:	
  3219 000061E6 8A25[396F0000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3220 000061EC B001                <1> 	mov	al, 1 ; sector count	
  3221                              <1> 	;int	13h
  3222 000061EE E85BC4FFFF          <1> 	call	int13h
  3223 000061F3 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3224 000061F5 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3225 000061F7 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3226 000061FA 7408                <1> 	je	short rwdsk_fails
  3227 000061FC FE0D[3B6F0000]      <1> 	dec	byte [retry_count]
  3228 00006202 7504                <1> 	jnz	short rwdsk_reset
  3229                              <1> rwdsk_fails:
  3230 00006204 F9                  <1> 	stc
  3231                              <1> rwdsk_ok:
  3232 00006205 5B                  <1> 	pop	ebx ; ***
  3233 00006206 5E                  <1> 	pop	esi ; ****
  3234 00006207 C3                  <1> 	retn
  3235                              <1> rwdsk_reset:
  3236                              <1> 	; 02/02/2015
  3237 00006208 28E4                <1> 	sub	ah, ah
  3238 0000620A 80FA80              <1> 	cmp	dl, 80h
  3239 0000620D 7202                <1> 	jb	short rwdsk_fd_reset
  3240 0000620F B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3241                              <1> rwdsk_fd_reset:
  3242                              <1> 	;int	13h
  3243 00006211 E838C4FFFF          <1>         call	int13h
  3244 00006216 73CE                <1> 	jnc	short rwdsk_retry
  3245 00006218 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3246 0000621A EBE9                <1> 	jmp 	short rwdsk_ok
  3247                              <1> 
  3248                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3249                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3250                              <1> ;
  3251                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3252                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3253                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3254                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3255                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3256                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3257                              <1> ; as in original unix v1.
  3258                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3259                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3260                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3261                              <1> ;
  3262                              <1> ; Erdogan tan (10/07/2015) 
  3263                              <1> 
  3264                              <1> ;drum: / interrupt handler
  3265                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3266                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3267                              <1> ;                                      / error
  3268                              <1> ;               br 3f / no, error
  3269                              <1> ;       br      2f / error
  3270                              <1> ;
  3271                              <1> ;disk:
  3272                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3273                              <1> ;       jmp     *$0f
  3274                              <1> ;0:
  3275                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3276                              <1> ;      	        br 3f / no, errors
  3277                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3278                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3279                              <1> ;                        / to 1f
  3280                              <1> ;       br      4f
  3281                              <1> ;1:
  3282                              <1> ;       bit     $20000,rkcs
  3283                              <1> ;       beq     4f / wait for seek complete
  3284                              <1> ;       mov     $0b,0b-2
  3285                              <1> ;       mov     rkap,r1
  3286                              <1> ;2:
  3287                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3288                              <1> ;                          / the disk buffer
  3289                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3290                              <1> ;       inc     r1
  3291                              <1> ;       asr     (r1)
  3292                              <1> ;       asr     (r1)
  3293                              <1> ;       asr     (r1) / reissue request
  3294                              <1> ;       dec     r1
  3295                              <1> ;3:
  3296                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3297                              <1> ;       mov     ac,-(sp)
  3298                              <1> ;       mov     mq,-(sp) / put these on the stack
  3299                              <1> ;       mov     sc,-(sp)
  3300                              <1> ;       jsr     r0,poke
  3301                              <1> ;       mov     (sp)+,sc
  3302                              <1> ;       mov     (sp)+,mq / pop them off stack
  3303                              <1> ;       mov     (sp)+,ac
  3304                              <1> ;4:
  3305                              <1> ;       jmp     retisp / u4-3
  3306                              <1> ;
  3307                              <1> ;trapt:                  / r2 points to the
  3308                              <1> ;       mov     (r0)+,r2 / device control register
  3309                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3310                              <1> ;       tst     (sp)+
  3311                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3312                              <1> ;       bge     4b / device still active so branch
  3313                              <1> ;       bit     (r0),active / was device busy?
  3314                              <1> ;       beq     4b / no, stray interrupt
  3315                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3316                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3317                              <1> ;       bge     2f / if no error jump to 2f
  3318                              <1> ;       tst     (r0)+ / skip on error
  3319                              <1> ; 2:
  3320                              <1> ;       jmp     (r0)
  2084                                  %include 'u9.s'      ; 29/06/2015
  2085                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2086                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2087                              <1> ; ****************************************************************************
  2088                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS9.INC
  2089                              <1> ; Last Modification: 24/12/2021
  2090                              <1> ; ----------------------------------------------------------------------------
  2091                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2092                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2093                              <1> ;
  2094                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2095                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2096                              <1> ; <Bell Laboratories (17/3/1972)>
  2097                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2098                              <1> ;
  2099                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2100                              <1> ;
  2101                              <1> ; ****************************************************************************
  2102                              <1> 
  2103                              <1> getch:
  2104                              <1> 	; 30/06/2015
  2105                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2106 0000621C 28C0                <1> 	sub	al, al ; 0
  2107                              <1> getch_q: ; 06/08/2015
  2108 0000621E 8A25[D66D0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2109 00006224 EB06                <1>         jmp     short getc_n
  2110                              <1> 
  2111                              <1> getc: 
  2112                              <1> 	; 12/11/2015
  2113                              <1> 	; 15/09/2015
  2114                              <1> 	; 01/07/2015
  2115                              <1> 	; 30/06/2015
  2116                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2117                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2118                              <1> 	;
  2119                              <1> 	; Retro UNIX 8086 v1 modification !
  2120                              <1> 	; 
  2121                              <1> 	; 'getc' gets (next) character 
  2122                              <1> 	;	 from requested TTY (keyboard) buffer 
  2123                              <1> 	; INPUTS ->
  2124                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2125                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2126                              <1> 	;	(Keyboard buffer will point to 
  2127                              <1> 	;			next character at next call)
  2128                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2129                              <1> 	;	(Keyboard buffer will point to 
  2130                              <1> 	;			current character at next call)
  2131                              <1> 	; OUTPUTS ->
  2132                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2133                              <1> 	;     			 ZF=0 -> AX has (current) character
  2134                              <1> 	;      AL = ascii code
  2135                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2136                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2137                              <1> 	; Original UNIX V1 'getc': 
  2138                              <1> 	;		get a character off character list
  2139                              <1> 	;
  2140                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2141                              <1> 	;
  2142                              <1> 	; 30/06/20045 (32 bit modifications)
  2143                              <1> 	; 16/07/2013
  2144                              <1> 	; mov 	[getctty], ah
  2145                              <1> 	;
  2146                              <1> 
  2147 00006226 8A25[D96E0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2148                              <1> getc_n:
  2149                              <1> 	; 30/06/2015
  2150 0000622C 08E4                <1> 	or	ah, ah
  2151 0000622E 740D                <1> 	jz	short getc0 
  2152 00006230 D0E4                <1> 	shl	ah, 1
  2153 00006232 0FB6DC              <1> 	movzx	ebx, ah
  2154 00006235 81C3[D86D0000]      <1> 	add	ebx, ttychr
  2155 0000623B EB05                <1> 	jmp	short getc1
  2156                              <1> getc0:
  2157 0000623D BB[D86D0000]        <1> 	mov	ebx, ttychr
  2158                              <1> getc1:
  2159 00006242 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2160                              <1> 				; (by kb_int)	
  2161 00006245 6609C9              <1> 	or	cx, cx
  2162 00006248 7507                <1> 	jnz	short getc2
  2163 0000624A 20C0                <1> 	and 	al, al
  2164 0000624C 7415                <1> 	jz	short getc_s
  2165                              <1> 	;xor	ax, ax
  2166                              <1> 	; 30/11/2021
  2167 0000624E 31C0                <1> 	xor	eax, eax
  2168 00006250 C3                  <1> 	retn
  2169                              <1> getc2:	
  2170 00006251 20C0                <1> 	and	al, al
  2171 00006253 6689C8              <1> 	mov	ax, cx
  2172 00006256 66B90000            <1> 	mov	cx, 0
  2173 0000625A 7506                <1> 	jnz	short getc3
  2174                              <1> getc_sn:
  2175 0000625C 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2176 0000625F 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2177                              <1> getc3:
  2178 00006262 C3                  <1> 	retn
  2179                              <1> getc_s:
  2180                              <1> 	; 12/11/2015
  2181                              <1> 	; 15/09/2015
  2182                              <1> 	; 01/07/2015
  2183                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2184                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2185                              <1> 	;
  2186                              <1> 	; tty  of the current process is not 
  2187                              <1> 	; current tty (ptty); so, current process only 
  2188                              <1> 	; can use keyboard input when its tty becomes 
  2189                              <1> 	; current tty (ptty).
  2190                              <1> 	; 'sleep' is for preventing an endless lock
  2191                              <1> 	; during this tty input request.
  2192                              <1> 	; (Because, the user is not looking at the video page
  2193                              <1> 	; of the process to undersand there is a keyboard
  2194                              <1> 	; input request.)
  2195                              <1> 	;
  2196                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2197                              <1> 	;
  2198                              <1> 	; 05/10/2013
  2199                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2200                              <1> 	;
  2201                              <1> 	; 10/10/2013
  2202                              <1> gcw0:
  2203 00006263 B10A                <1> 	mov	cl, 10 ; ch = 0
  2204                              <1> gcw1:	
  2205                              <1> 	; 12/11/2015
  2206 00006265 E862DAFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2207                              <1> 	; 10/10/2013
  2208 0000626A E880EBFFFF          <1> 	call	idle
  2209 0000626F 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2210                              <1> 				; (by kb_int)
  2211 00006272 6609C0              <1> 	or	ax, ax
  2212                              <1> ;	jnz	short gcw3
  2213 00006275 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2214                              <1> 	; 30/06/2015
  2215 00006277 FEC9                <1> 	dec	cl
  2216 00006279 75EA                <1> 	jnz	short gcw1
  2217                              <1> 	;
  2218 0000627B 8A25[D96E0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2219                              <1> ;	; 10/12/2013
  2220                              <1> ;	cmp 	ah, [ptty]
  2221                              <1> ;	jne	short gcw2
  2222                              <1> ;	; 14/02/2014
  2223                              <1> ;	cmp	byte [u.uno], 1
  2224                              <1> ;	jna	short gcw0		
  2225                              <1> ;gcw2:
  2226 00006281 E8FCEBFFFF          <1> 	call	sleep
  2227                              <1> 	;
  2228                              <1> 	; 20/09/2013
  2229 00006286 8A25[D96E0000]      <1> 	mov	ah, [u.ttyn]
  2230 0000628C 30C0                <1> 	xor 	al, al
  2231 0000628E EB9C                <1> 	jmp	short getc_n
  2232                              <1> ;gcw3:
  2233                              <1> gcw2: 	; 15/09/2015
  2234                              <1> 	; 10/10/2013
  2235 00006290 30C9                <1> 	xor	cl, cl
  2236 00006292 EBC8                <1> 	jmp	short getc_sn
  2237                              <1> 
  2238                              <1> putc:	
  2239                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2240                              <1> 	; 13/08/2015
  2241                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2242                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2243                              <1> 	;
  2244                              <1> 	; Retro UNIX 8086 v1 modification !
  2245                              <1> 	; 
  2246                              <1> 	; 'putc' puts a character 
  2247                              <1> 	;	 onto requested (tty) video page or
  2248                              <1> 	;	 serial port
  2249                              <1> 	; INPUTS ->
  2250                              <1> 	;     AL = ascii code of the character
  2251                              <1> 	;     AH = video page (tty) number (0 to 7)
  2252                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2253                              <1> 	; OUTPUTS ->
  2254                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2255                              <1> 	;      			ZF=0 -> AX has (current) character
  2256                              <1> 	;     cf=0 and AH = 0 -> no error
  2257                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)
  2258                              <1> 	; 
  2259                              <1> 	; Original UNIX V1 'putc': 
  2260                              <1> 	;     put a character at the end of character list
  2261                              <1> 	;
  2262                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2263                              <1> 	;
  2264 00006294 80FC07              <1> 	cmp	ah, 7
  2265 00006297 770A                <1>         ja      short sndc ; 05/12/2021
  2266                              <1> 	; 30/06/2015
  2267 00006299 0FB6DC              <1> 	movzx	ebx, ah
  2268                              <1> 	; 13/08/2015
  2269 0000629C B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2270 0000629E E919B1FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2271                              <1> 
  2272                              <1> sndc:   ; <Send character>
  2273                              <1> 	;
  2274                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2275                              <1> 	; 17/11/2015
  2276                              <1> 	; 16/11/2015
  2277                              <1> 	; 11/11/2015
  2278                              <1> 	; 10/11/2015
  2279                              <1> 	; 09/11/2015
  2280                              <1> 	; 08/11/2015
  2281                              <1> 	; 07/11/2015
  2282                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2283                              <1> 	; 29/10/2015
  2284                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2285                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2286                              <1> 	;
  2287                              <1> 	; Retro UNIX 8086 v1 feature only !
  2288                              <1> 	;
  2289                              <1> 	; ah = [u.ttyn]
  2290                              <1> 	;
  2291                              <1> 	; 30/06/2015
  2292 000062A3 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2293                              <1> 	; 07/11/2015
  2294 000062A6 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2295                              <1> sndc0:
  2296                              <1> 	; 07/11/2015
  2297 000062A9 E82AECFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2298 000062AE 7405                <1> 	jz	short sndc1
  2299 000062B0 E817DAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2300                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2301                              <1> sndc1:
  2302                              <1> 	; 16/11/2015
  2303                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2304                              <1> 	; 24/12/2021
  2305 000062B5 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2306                              <1> sndcx:
  2307 000062B7 8A83[1A6E0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2308 000062BD 8AA3[186E0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2309                              <1> 	;
  2310                              <1> 	; 17/11/2015
  2311                              <1> 	; check 'request for response' status
  2312 000062C3 80BB[146E0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2313 000062CA 740A                <1> 	jz	short query
  2314                              <1> response:
  2315 000062CC FE05[176E0000]      <1> 	inc 	byte [comqr] ; query or response status
  2316 000062D2 B0FF                <1> 	mov	al, 0FFh	 
  2317 000062D4 EB14                <1> 	jmp	short sndc3
  2318                              <1> query:
  2319 000062D6 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2320 000062D8 750E                <1> 	jnz 	short sndc2 ; normal character
  2321                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2322                              <1> 	;je	short sndc2  ; yes, already responded
  2323                              <1> 	; 16/11/2015
  2324                              <1> 	; query: request for response (again)
  2325 000062DA 8883[186E0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2326 000062E0 FE05[176E0000]      <1> 	inc 	byte [comqr] ; query or response status
  2327 000062E6 EB02                <1> 	jmp	short sndc3
  2328                              <1> sndc2:
  2329 000062E8 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2330                              <1> sndc3:
  2331 000062EA 8883[1A6E0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2332 000062F0 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2333                              <1> 	; 30/06/2015
  2334 000062F2 E837D3FFFF          <1> 	call	sp_status ; get serial port status
  2335                              <1> 	; AL = Line status, AH = Modem status
  2336                              <1> 	; 07/11/2015
  2337 000062F7 A880                <1> 	test	al, 80h
  2338 000062F9 7504                <1> 	jnz	short sndc4
  2339 000062FB A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2340 000062FD 751B                <1> 	jnz	short sndc5
  2341                              <1> sndc4: 	; Check line status again
  2342                              <1> 	; 16/11/2015
  2343                              <1> 	;push	cx
  2344                              <1> 	; 24/12/2021
  2345 000062FF 51                  <1> 	push	ecx
  2346 00006300 B906000000          <1> 	mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2347 00006305 E8C1B1FFFF          <1> 	call	WAITF
  2348                              <1> 	;pop	cx
  2349                              <1> 	; 24/12/1021
  2350 0000630A 59                  <1> 	pop	ecx
  2351                              <1> 	;
  2352 0000630B 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2353 0000630D E81CD3FFFF          <1> 	call	sp_status ; get serial port status
  2354                              <1> 	; 16/11/2015
  2355                              <1> 	; 09/11/2015
  2356                              <1> 	; 08/11/2015
  2357 00006312 A880                <1> 	test	al, 80h	; time out error
  2358 00006314 7566                <1>         jnz     short sndc7
  2359 00006316 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2360 00006318 7462                <1>         jz	short sndc7
  2361                              <1> sndc5:  
  2362 0000631A 8A83[1A6E0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2363 00006320 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2364 00006324 28DE                <1> 	sub	dh, bl
  2365 00006326 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 00006327 51                  <1> 	push	ecx
  2375 00006328 B906000000          <1> 	mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2376 0000632D E899B1FFFF          <1> 	call	WAITF
  2377                              <1> 	;pop	cx
  2378                              <1> 	; 24/12/1021
  2379 00006332 59                  <1> 	pop	ecx
  2380                              <1>     	;
  2381                              <1> 	; 07/11/2015
  2382 00006333 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2383                              <1> 	;
  2384 00006335 E8F4D2FFFF          <1> 	call	sp_status ; get serial port status
  2385                              <1> 	; AL = Line status, AH = Modem status
  2386                              <1> 	;
  2387 0000633A E899EBFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2388 0000633F 7405                <1> 	jz	short sndc6
  2389 00006341 E886D9FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2390                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2391                              <1> sndc6:
  2392 00006346 3C80                <1> 	cmp	al, 80h
  2393 00006348 7332                <1> 	jnb	short sndc7		
  2394                              <1> 	;
  2395 0000634A 803D[176E0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2396 00006351 7244                <1> 	jb	short sndc8 	; no, normal character
  2397 00006353 883D[176E0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2398                              <1> 	; 17/11/2015
  2399 00006359 E891EAFFFF          <1> 	call	idle
  2400                              <1> 	;
  2401 0000635E 38BB[1A6E0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2402                              <1>         ;ja	sndc2       ; response (will be followed by
  2403                              <1> 			    ; a normal character)
  2404                              <1> 	; 24/12/2021
  2405 00006364 7602                <1> 	jna	short sndc_10
  2406 00006366 EB80                <1> 	jmp	sndc2
  2407                              <1> sndc_10:
  2408                              <1> 	; Query request must be responded by the terminal
  2409                              <1> 	; before sending a normal character !
  2410 00006368 53                  <1> 	push	ebx
  2411                              <1> 	;push	cx ; *** cl = character (to be sent)
  2412                              <1> 	; 24/12/2021
  2413 00006369 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2414 0000636A 8A25[D96E0000]      <1> 	mov	ah, [u.ttyn]
  2415 00006370 E80DEBFFFF          <1> 	call	sleep ; this process will be awakened by
  2416                              <1> 		      ; received data available interrupt
  2417                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2418                              <1> 	; 24/12/2021
  2419 00006375 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2420 00006376 5B                  <1> 	pop	ebx
  2421 00006377 E93BFFFFFF          <1>         jmp	sndcx
  2422                              <1> sndc7:
  2423                              <1> 	 ; 16/11/2015
  2424 0000637C 803D[176E0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2425 00006383 7213                <1> 	jb	short sndc9 	; no
  2426                              <1> 	;
  2427 00006385 88BB[186E0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2428 0000638B 88BB[1A6E0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2429                              <1> 	;
  2430 00006391 883D[176E0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2431                              <1> sndc8:
  2432 00006397 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2433                              <1> sndc9:
  2434                              <1> 	; AL = Line status, AH = Modem status
  2435 00006398 C3                  <1> 	retn
  2436                              <1> 
  2437                              <1> get_cpos:
  2438                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2439                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2440                              <1> 	;
  2441                              <1> 	; INPUT -> bl = video page number
  2442                              <1> 	; RETURN -> dx = cursor position
  2443                              <1> 
  2444 00006399 53                  <1> 	push	ebx
  2445 0000639A 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2446 0000639D D0E3                <1> 	shl	bl, 1
  2447 0000639F 81C3[C66D0000]      <1> 	add	ebx, cursor_posn
  2448 000063A5 668B13              <1> 	mov	dx, [ebx]
  2449 000063A8 5B                  <1> 	pop	ebx
  2450 000063A9 C3                  <1> 	retn
  2451                              <1> 
  2452                              <1> read_ac_current:
  2453                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2454                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2455                              <1> 	;
  2456                              <1> 	; INPUT -> bl = video page number
  2457                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2458                              <1> 
  2459 000063AA E88BB1FFFF          <1> 	call 	find_position ; 'video.inc'
  2460                              <1> 	; dx = status port
  2461                              <1> 	; esi = cursor location/address
  2462 000063AF 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2463 000063B5 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2464 000063B8 C3                  <1> 	retn
  2465                              <1> 
  2466                              <1> syssleep:
  2467                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2468                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2469                              <1> 	;
  2470                              <1> 	; Retro UNIX 8086 v1 feature only
  2471                              <1> 	; (INPUT -> none)
  2472                              <1> 	;
  2473 000063B9 0FB61D[F56E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2474 000063C0 8AA3[DF6B0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2475 000063C6 E8B7EAFFFF          <1> 	call	sleep
  2476 000063CB E9FCD7FFFF          <1> 	jmp	sysret
  2477                              <1> 
  2478                              <1> vp_clr:
  2479                              <1> 	; Reset/Clear Video Page
  2480                              <1> 	;
  2481                              <1> 	; 05/12/2021 - (Retro UNIX 386 v1.2)
  2482                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2483                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2484                              <1> 	;
  2485                              <1> 	; Retro UNIX 8086 v1 feature only !
  2486                              <1> 	;
  2487                              <1> 	; INPUTS -> 
  2488                              <1> 	;   BL = video page number	 
  2489                              <1> 	;
  2490                              <1> 	; OUTPUT ->
  2491                              <1> 	;   none
  2492                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2493                              <1> 	;
  2494                              <1> 	; 04/12/2013
  2495 000063D0 28C0                <1> 	sub	al, al
  2496                              <1> 	; al = 0 (clear video page)
  2497                              <1> 	; bl = video page
  2498 000063D2 B407                <1> 	mov	ah, 07h
  2499                              <1> 	; ah = 7 (attribute/color)
  2500                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2501                              <1> 	; 05/12/2021
  2502 000063D4 31C9                <1> 	xor	ecx, ecx
  2503 000063D6 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2504 000063DA E885B1FFFF          <1> 	call	scroll_up
  2505                              <1> 	; bl = video page
  2506                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2507                              <1> 	; 05/12/2021
  2508 000063DF 31D2                <1> 	xor	edx, edx
  2509 000063E1 E9F8B0FFFF          <1> 	jmp 	set_cpos
  2510                              <1> 
  2511                              <1> sysmsg:
  2512                              <1> 	; 11/12/2021
  2513                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2514                              <1> 	; 11/11/2015
  2515                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2516                              <1> 	; Print user-application message on user's console tty
  2517                              <1> 	;
  2518                              <1> 	; Input -> EBX = Message address
  2519                              <1> 	;	   ECX = Message length (max. 255)
  2520                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2521                              <1> 	;
  2522 000063E6 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2523                              <1> 	;ja	sysret ; nothing to do with big message size
  2524 000063EC 7779                <1> 	ja	short sysmsg8 ; 11/12/2021
  2525 000063EE 08C9                <1> 	or	cl, cl
  2526                              <1> 	;jz	sysret
  2527 000063F0 7475                <1> 	jz	short sysmsg8 ; 11/12/2021
  2528 000063F2 20D2                <1> 	and	dl, dl
  2529 000063F4 7502                <1> 	jnz	short sysmsg0
  2530 000063F6 B207                <1> 	mov	dl, 07h ; default color
  2531                              <1> 		; (black background, light gray character)
  2532                              <1> sysmsg0:
  2533 000063F8 891D[C86E0000]      <1> 	mov	[u.base], ebx
  2534 000063FE 8815[D76D0000]      <1> 	mov	[ccolor], dl ; color attributes
  2535 00006404 89E5                <1> 	mov	ebp, esp
  2536 00006406 31DB                <1> 	xor	ebx, ebx ; 0
  2537 00006408 891D[D06E0000]      <1> 	mov	[u.nread], ebx ; 0
  2538                              <1> 	;
  2539 0000640E 381D[166F0000]      <1> 	cmp	[u.kcall], bl ; 0
  2540 00006414 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2541                              <1> 	;
  2542 00006416 890D[CC6E0000]      <1> 	mov	[u.count], ecx
  2543 0000641C 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ ; 04/12/2021
  2544                              <1> 	; 04/12/2021
  2545                              <1> 	; (dword alignment for esp)
  2546 0000641D F6C103              <1> 	test	cl, 3
  2547 00006420 7404                <1> 	jz	short sysmsg_7
  2548 00006422 80C903              <1> 	or	cl, 3
  2549 00006425 41                  <1> 	inc	ecx
  2550                              <1> sysmsg_7:
  2551 00006426 29CC                <1> 	sub	esp, ecx
  2552 00006428 89E7                <1> 	mov	edi, esp
  2553 0000642A 89E6                <1> 	mov	esi, esp
  2554 0000642C 66891D[106F0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2555                              <1> 	; 11/11/2015
  2556 00006433 8A25[DA6E0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2557                              <1> 	; 0 = none
  2558 00006439 FECC                <1> 	dec	ah
  2559 0000643B 790C                <1> 	jns	short sysmsg1 
  2560 0000643D 8A1D[F56E0000]      <1> 	mov	bl, [u.uno] ; process number	
  2561 00006443 8AA3[DF6B0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2562                              <1> sysmsg1:
  2563 00006449 8825[D96E0000]      <1> 	mov	[u.ttyn], ah
  2564                              <1> sysmsg2:
  2565 0000644F E837F5FFFF          <1> 	call	cpass
  2566 00006454 7416                <1> 	jz	short sysmsg5
  2567 00006456 AA                  <1> 	stosb
  2568 00006457 20C0                <1> 	and	al, al
  2569 00006459 75F4                <1> 	jnz	short sysmsg2
  2570                              <1> sysmsg3:
  2571 0000645B 80FC07              <1> 	cmp	ah, 7 ; tty number
  2572 0000645E 7711                <1> 	ja	short sysmsg6 ; serial port
  2573 00006460 E83E000000          <1> 	call	print_cmsg
  2574                              <1> sysmsg4:
  2575 00006465 89EC                <1> 	mov	esp, ebp
  2576                              <1> sysmsg8: ; 11/12/2021	
  2577 00006467 E960D7FFFF          <1> 	jmp	sysret
  2578                              <1> sysmsg5:
  2579 0000646C C60700              <1> 	mov	byte [edi], 0
  2580 0000646F EBEA                <1> 	jmp	short sysmsg3
  2581                              <1> sysmsg6:
  2582 00006471 8A06                <1> 	mov	al, [esi]
  2583 00006473 E82BFEFFFF          <1> 	call	sndc
  2584 00006478 72EB                <1> 	jc	short sysmsg4
  2585 0000647A 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2586 0000647D 76E6                <1> 	jna	short sysmsg4
  2587 0000647F 46                  <1> 	inc 	esi
  2588 00006480 8A25[D96E0000]      <1> 	mov	ah, [u.ttyn]
  2589 00006486 EBE9                <1> 	jmp	short sysmsg6
  2590                              <1> 
  2591                              <1> sysmsgk: ; Temporary (01/07/2015)
  2592                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2593                              <1> 	; (ECX -character count- will not be considered)
  2594 00006488 8B35[C86E0000]      <1> 	mov	esi, [u.base]
  2595 0000648E 8A25[D66D0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2596 00006494 8825[D96E0000]      <1> 	mov	[u.ttyn], ah
  2597 0000649A C605[166F0000]00    <1> 	mov	byte [u.kcall], 0
  2598 000064A1 EBB8                <1> 	jmp	short sysmsg3
  2599                              <1> 	
  2600                              <1> print_cmsg: 
  2601                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2602                              <1> 	;
  2603                              <1> 	; print message (on user's console tty) 
  2604                              <1> 	;	with requested color
  2605                              <1> 	;
  2606                              <1> 	; INPUTS:
  2607                              <1> 	;	esi = message address
  2608                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2609                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2610                              <1> 	;
  2611 000064A3 AC                  <1> 	lodsb
  2612                              <1> pcmsg1:
  2613 000064A4 56                  <1> 	push 	esi
  2614 000064A5 0FB61D[D96E0000]    <1>         movzx   ebx, byte [u.ttyn]
  2615 000064AC 8A25[D76D0000]      <1> 	mov	ah, [ccolor]
  2616 000064B2 E805AFFFFF          <1> 	call 	write_tty
  2617 000064B7 5E                  <1> 	pop	esi
  2618 000064B8 AC                  <1> 	lodsb
  2619 000064B9 20C0                <1> 	and 	al, al  ; 0
  2620 000064BB 75E7                <1> 	jnz 	short pcmsg1
  2621 000064BD C3                  <1> 	retn
  2622                              <1> 
  2623                              <1> sysgeterr:
  2624                              <1> 	; 09/12/2015
  2625                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2626                              <1> 	; Get last error number or page fault count
  2627                              <1> 	; (for debugging)
  2628                              <1> 	;
  2629                              <1> 	; Input -> EBX = return type
  2630                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2631                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2632                              <1> 	;	   FFFFFFFEh = total page fault count
  2633                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2634                              <1> 	;
  2635                              <1> 	; Output -> EAX = last error number or page fault count
  2636                              <1> 	;	   (depending on EBX input)
  2637                              <1> 	; 	
  2638 000064BE 21DB                <1> 	and 	ebx, ebx
  2639 000064C0 750B                <1> 	jnz	short glerr_2
  2640                              <1> glerr_0:
  2641 000064C2 A1[186F0000]        <1> 	mov	eax, [u.error]
  2642                              <1> glerr_1:
  2643 000064C7 A3[A46E0000]        <1> 	mov	[u.r0], eax
  2644 000064CC C3                  <1>  	retn
  2645                              <1> glerr_2:
  2646 000064CD 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2647 000064CE 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2648 000064D0 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2649 000064D1 75EF                <1> 	jnz	short glerr_0
  2650 000064D3 A1[606E0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2651 000064D8 EBED                <1>         jmp     short glerr_1
  2652                              <1> glerr_3:
  2653 000064DA A1[1C6F0000]        <1> 	mov 	eax, [u.pfcount]
  2654 000064DF EBE6                <1> 	jmp	short glerr_1
  2085                                  
  2086                                  ; 07/03/2015
  2087                                  ; Temporary Code
  2088                                  display_disks:
  2089 000064E1 803D[9E680000]00        	cmp 	byte [fd0_type], 0
  2090 000064E8 7605                    	jna 	short ddsks1
  2091 000064EA E87D000000              	call	pdskm
  2092                                  ddsks1:
  2093 000064EF 803D[9F680000]00        	cmp	byte [fd1_type], 0
  2094 000064F6 760C                    	jna	short ddsks2
  2095 000064F8 C605[8F6A0000]31        	mov	byte [dskx], '1'
  2096 000064FF E868000000              	call	pdskm
  2097                                  ddsks2:
  2098 00006504 803D[A0680000]00        	cmp	byte [hd0_type], 0
  2099 0000650B 7654                    	jna	short ddsk6
  2100 0000650D 66C705[8D6A0000]68-     	mov	word [dsktype], 'hd'
  2100 00006515 64                 
  2101 00006516 C605[8F6A0000]30        	mov	byte [dskx], '0'
  2102 0000651D E84A000000              	call	pdskm
  2103                                  ddsks3:
  2104 00006522 803D[A1680000]00        	cmp	byte [hd1_type], 0
  2105 00006529 7636                    	jna	short ddsk6
  2106 0000652B C605[8F6A0000]31        	mov	byte [dskx], '1'
  2107 00006532 E835000000              	call	pdskm
  2108                                  ddsks4:
  2109 00006537 803D[A2680000]00        	cmp	byte [hd2_type], 0
  2110 0000653E 7621                    	jna	short ddsk6
  2111 00006540 C605[8F6A0000]32        	mov	byte [dskx], '2'
  2112 00006547 E820000000              	call	pdskm
  2113                                  ddsks5:
  2114 0000654C 803D[A3680000]00        	cmp	byte [hd3_type], 0
  2115 00006553 760C                    	jna	short ddsk6
  2116 00006555 C605[8F6A0000]33        	mov	byte [dskx], '3'
  2117 0000655C E80B000000              	call	pdskm
  2118                                  ddsk6:
  2119 00006561 BE[9E6A0000]            	mov	esi, nextline
  2120 00006566 E806000000              	call	pdskml
  2121                                  pdskm_ok:
  2122 0000656B C3                      	retn
  2123                                  pdskm:
  2124 0000656C BE[8B6A0000]            	mov	esi, dsk_ready_msg
  2125                                  pdskml:	
  2126 00006571 AC                      	lodsb
  2127 00006572 08C0                    	or	al, al
  2128 00006574 74F5                    	jz	short pdskm_ok
  2129 00006576 56                      	push	esi
  2130 00006577 31DB                    	xor	ebx, ebx ; 0
  2131                                  			; Video page 0 (bl=0)
  2132 00006579 B407                    	mov	ah, 07h ; Black background, 
  2133                                  			; light gray forecolor
  2134 0000657B E83CAEFFFF              	call	write_tty
  2135 00006580 5E                      	pop	esi
  2136 00006581 EBEE                    	jmp	short pdskml
  2137                                  
  2138 00006583 90<rep Dh>              align 16
  2139                                  
  2140                                  gdt:	; Global Descriptor Table
  2141                                  	; (30/07/2015, conforming cs)
  2142                                  	; (26/03/2015)
  2143                                  	; (24/03/2015, tss)
  2144                                  	; (19/03/2015)
  2145                                  	; (29/12/2013)
  2146                                  	;
  2147 00006590 0000000000000000        	dw 0, 0, 0, 0	; NULL descriptor
  2148                                  	; 18/08/2014
  2149                                  			; 8h kernel code segment, base = 00000000h		
  2150 00006598 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2151                                  			; 10h kernel data segment, base = 00000000h	
  2152 000065A0 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2153                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2154 000065A8 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2155                                  			; 23h user data segment, base address = 400000h ; CORE
  2156 000065B0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2157                                  			; Task State Segment
  2158 000065B8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2159                                  			       ;  no IO permission in ring 3)
  2160                                  gdt_tss0:
  2161 000065BA 0000                    	dw 0  ; TSS base address, bits 0-15 
  2162                                  gdt_tss1:
  2163 000065BC 00                      	db 0  ; TSS base address, bits 16-23 
  2164                                  	      		; 49h	
  2165 000065BD E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2166 000065BE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2167                                  gdt_tss2:
  2168 000065BF 00                      	db 0  ; TSS base address, bits 24-31 
  2169                                  
  2170                                  gdt_end:
  2171                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2172                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2173                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2174                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2175                                  
  2176                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2177                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2178                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2179                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2180                                  		; W= Writeable, A= Accessed
  2181                                  	
  2182                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2183                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2184                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2185                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2186                                  
  2187                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2188                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2189                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2190                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2191                                  	
  2192                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2193                                  
  2194                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2195                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2196                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2197                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2198                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2199                                  		; AVL= Available to programmers	
  2200                                  
  2201                                  gdtd:
  2202 000065C0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2203 000065C2 [90650000]                      dd gdt			; Address of the GDT
  2204                                  
  2205                                  	; 20/08/2014
  2206                                  idtd:
  2207 000065C6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2208 000065C8 [406B0000]                      dd idt			; Address of the IDT
  2209                                  
  2210                                  Align 4
  2211                                  
  2212                                  	; 21/08/2014
  2213                                  ilist:
  2214                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2215                                  	;
  2216                                  	; Exception list
  2217                                  	; 25/08/2014	
  2218 000065CC [20080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2219 000065D0 [27080000]              	dd	exc1	
  2220 000065D4 [2E080000]              	dd 	exc2	
  2221 000065D8 [35080000]              	dd	exc3	
  2222 000065DC [39080000]              	dd	exc4	
  2223 000065E0 [3D080000]              	dd	exc5	
  2224 000065E4 [41080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2225 000065E8 [45080000]              	dd	exc7	
  2226 000065EC [49080000]              	dd	exc8	
  2227 000065F0 [4D080000]              	dd	exc9	
  2228 000065F4 [51080000]              	dd 	exc10	
  2229 000065F8 [55080000]              	dd	exc11
  2230 000065FC [59080000]              	dd	exc12
  2231 00006600 [5D080000]              	dd	exc13	; 0Dh, General Protection Fault
  2232 00006604 [61080000]              	dd 	exc14	; 0Eh, Page Fault
  2233 00006608 [65080000]              	dd	exc15
  2234 0000660C [69080000]              	dd	exc16
  2235 00006610 [6D080000]              	dd	exc17
  2236 00006614 [71080000]              	dd 	exc18
  2237 00006618 [75080000]              	dd	exc19
  2238 0000661C [79080000]              	dd 	exc20
  2239 00006620 [7D080000]              	dd	exc21
  2240 00006624 [81080000]              	dd	exc22
  2241 00006628 [85080000]              	dd	exc23
  2242 0000662C [89080000]              	dd 	exc24
  2243 00006630 [8D080000]              	dd	exc25
  2244 00006634 [91080000]              	dd	exc26
  2245 00006638 [95080000]              	dd	exc27
  2246 0000663C [99080000]              	dd 	exc28
  2247 00006640 [9D080000]              	dd	exc29
  2248 00006644 [A1080000]              	dd 	exc30
  2249 00006648 [A5080000]              	dd	exc31
  2250                                  	; Interrupt list
  2251 0000664C [5E060000]              	dd	timer_int	; INT 20h
  2252                                  		;dd	irq0	
  2253 00006650 [580B0000]              	dd	keyb_int	; 27/08/2014
  2254                                  		;dd	irq1
  2255 00006654 [7A070000]              	dd	irq2
  2256                                  		; COM2 int
  2257 00006658 [7E070000]              	dd	irq3
  2258                                  		; COM1 int
  2259 0000665C [89070000]              	dd	irq4
  2260 00006660 [94070000]              	dd	irq5
  2261                                  ;DISKETTE_INT: ;06/02/2015
  2262 00006664 [FB250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2263                                  		;dd	irq6
  2264                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2265                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2266 00006668 [090B0000]              	dd	default_irq7	; 25/02/2015
  2267                                  		;dd	irq7
  2268                                  ; Real Time Clock Interrupt
  2269 0000666C [AE090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2270                                  		;dd	irq8	; INT 28h
  2271 00006670 [A4070000]              	dd	irq9
  2272 00006674 [A8070000]              	dd	irq10
  2273 00006678 [AC070000]              	dd	irq11
  2274 0000667C [B0070000]              	dd	irq12
  2275 00006680 [B4070000]              	dd	irq13
  2276                                  ;HDISK_INT1:  ;06/02/2015 	
  2277 00006684 [212E0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2278                                  		;dd	irq14
  2279                                  ;HDISK_INT2:  ;06/02/2015
  2280 00006688 [442E0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2281                                  		;dd	irq15	; INT 2Fh
  2282                                  		; 14/08/2015
  2283 0000668C [A83A0000]              	dd	sysent		; INT 30h (system calls)
  2284                                  	
  2285                                  	;dd	ignore_int
  2286 00006690 00000000                	dd	0
  2287                                  
  2288                                  ;;;
  2289                                  ;;; 11/03/2015
  2290                                  %include 'kybdata.s'	; KEYBOARD (BIOS) DATA
  2291                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2292                              <1> ; Last Modification: 11/03/2015
  2293                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2294                              <1> ;
  2295                              <1> ; ///////// KEYBOARD DATA ///////////////
  2296                              <1> 
  2297                              <1> ; 05/12/2014
  2298                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2299                              <1> ; 03/06/86  KEYBOARD BIOS
  2300                              <1> 
  2301                              <1> ;---------------------------------------------------------------------------------
  2302                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2303                              <1> ;---------------------------------------------------------------------------------
  2304                              <1> 
  2305                              <1> ;-----	TABLES FOR ALT CASE ------------
  2306                              <1> ;-----	ALT-INPUT-TABLE 
  2307 00006694 524F50514B          <1> K30:	db	82,79,80,81,75
  2308 00006699 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2309                              <1> ;-----	SUPER-SHIFT-TABLE 
  2310 0000669E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2311 000066A4 161718191E1F        <1> 	db	22,23,24,25,30,31
  2312 000066AA 202122232425        <1> 	db	32,33,34,35,36,37
  2313 000066B0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2314 000066B6 3132                <1> 	db	49,50
  2315                              <1> 
  2316                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2317                              <1> ;-----	KEY_TABLE 
  2318 000066B8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2319 000066B9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2320 000066BE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2321                              <1> _K6L    equ     $-_K6
  2322                              <1> 
  2323                              <1> ;-----	MASK_TABLE
  2324 000066C0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2325 000066C1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2326 000066C6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2327                              <1> 
  2328                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2329 000066C8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2330 000066CE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2331 000066D4 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2332 000066DA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2333 000066E0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2334 000066E6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2335 000066EC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2336 000066F2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2337 000066F8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2338 000066FE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2339                              <1> 	;				;----- FUNCTIONS ------		
  2340 00006702 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2341 00006708 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2342 0000670E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2343 00006714 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2344 0000671A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2345                              <1> 
  2346                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2347 00006720 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2347 00006729 39302D3D0809        <1>
  2348 0000672F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2348 00006738 705B5D0DFF61736466- <1>
  2348 00006741 67686A6B6C3B27      <1>
  2349 00006748 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2349 00006751 6D2C2E2FFF2AFF20FF  <1>
  2350                              <1> ;-----	LC TABLE SCAN
  2351 0000675A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2352 0000675F 4041424344          <1> 	db	64,65,66,67,68
  2353 00006764 FFFF                <1> 	db	-1,-1			; NL, SL
  2354                              <1> 
  2355                              <1> ;-----	KEYPAD TABLE
  2356 00006766 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2357 0000676C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2358 00006773 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2359                              <1> 
  2360                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2361 00006778 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2361 00006781 28295F2B0800        <1>
  2362 00006787 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2362 00006790 507B7D0DFF41534446- <1>
  2362 00006799 47484A4B4C3A22      <1>
  2363 000067A0 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2363 000067A9 4D3C3E3FFF2AFF20FF  <1>
  2364                              <1> ;-----	UC TABLE SCAN
  2365 000067B2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2366 000067B7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2367 000067BC FFFF                <1> 	db	-1,-1			; NL, SL
  2368                              <1> 
  2369                              <1> ;-----	NUM STATE TABLE
  2370 000067BE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2370 000067C7 3233302E            <1>
  2371                              <1> 	;
  2372 000067CB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2373                              <1> 
  2374                              <1> Align	4
  2375                              <1> ;----------------------------------------
  2376                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2377                              <1> ;----------------------------------------
  2378 000067D0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2379 000067D1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2380                              <1> 				; (29h default setting for video mode 3)
  2381                              <1> 				; Mode Select register Bits
  2382                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2383                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2384                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2385                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2386                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2387                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2388                              <1> 				;   BIT 6, 7 - Not Used
  2389                              <1> 
  2390                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2391                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2392                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2393                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2394                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2395                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2396                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2397                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2398                              <1> ; Mode & 37h = Video signal OFF
  2399                              <1> 			
  2400                              <1> 
  2401                              <1> ; 26/08/2014
  2402                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2403                              <1> ; Derived from IBM "pc-at" 
  2404                              <1> ; rombios source code (06/10/1985)
  2405                              <1> ; 'dseg.inc'
  2406                              <1> 
  2407                              <1> ;---------------------------------------;
  2408                              <1> ;	SYSTEM DATA AREA		;
  2409                              <1> ;----------------------------------------
  2410 000067D2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2411                              <1> 
  2412                              <1> ;----------------------------------------
  2413                              <1> ;	KEYBOARD DATA AREAS		;
  2414                              <1> ;----------------------------------------
  2415                              <1> 
  2416 000067D3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2417 000067D4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2418 000067D5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2419 000067D6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2420 000067D7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2421 000067D8 [E8670000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2422 000067DC [08680000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2423 000067E0 [E8670000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2424 000067E4 [E8670000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2425                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2426 000067E8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2427                              <1> 
  2428                              <1> ; /// End Of KEYBOARD DATA ///
  2291                                  %include 'vidata.s'	; VIDEO (BIOS) DATA
  2292                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2293                              <1> ; Last Modification: 11/03/2015
  2294                              <1> ;		    (Data section for 'VIDEO.INC')	
  2295                              <1> ;
  2296                              <1> ; ///////// VIDEO DATA ///////////////
  2297                              <1> 
  2298                              <1> video_params:
  2299                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2300                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2301                              <1> 	; VIDEO MODE 3
  2302 00006808 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2303 0000680F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2304 00006814 00000000            <1> 	db	0,0,0,0
  2305                              <1> 
  2306                              <1> ; /// End Of VIDEO DATA ///
  2292                                  %include 'diskdata.s'	; DISK (BIOS) DATA (initialized)
  2293                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2294                              <1> ; Last Modification: 11/03/2015
  2295                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2296                              <1> ;
  2297                              <1> ; *****************************************************************************
  2298                              <1> 
  2299                              <1> ;----------------------------------------
  2300                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2301                              <1> ;	REFERENCED BY POST & BIOS	:
  2302                              <1> ;----------------------------------------
  2303                              <1> 
  2304 00006818 [7B680000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2305                              <1> 
  2306                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2307                              <1> ;----------------------------------------------------------------
  2308                              <1> ; DISK_BASE							:
  2309                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2310                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2311                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2312                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2313                              <1> ;----------------------------------------------------------------
  2314                              <1> 
  2315                              <1> ;DISK_BASE:	
  2316                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2317                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2318                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2319                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2320                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2321                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2322                              <1> ;	DB	01BH		; GAP LENGTH
  2323                              <1> ;	DB	0FFH		; DTL
  2324                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2325                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2326                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2327                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2328                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2329                              <1> 
  2330                              <1> ;----------------------------------------
  2331                              <1> ;	ROM BIOS DATA AREAS		:
  2332                              <1> ;----------------------------------------
  2333                              <1> 
  2334                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2335                              <1> 
  2336                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2337                              <1> 
  2338                              <1> ;----------------------------------------
  2339                              <1> ;	DISKETTE DATA AREAS		:
  2340                              <1> ;----------------------------------------
  2341                              <1> 
  2342                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2343                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2344                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2345                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2346                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2347                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2348                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2349                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2350                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2351                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2352                              <1> 
  2353                              <1> ;----------------------------------------
  2354                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2355                              <1> ;----------------------------------------
  2356                              <1> 
  2357                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2358                              <1> 
  2359                              <1> ;----------------------------------------
  2360                              <1> ;	TIMER DATA AREA 		:
  2361                              <1> ;----------------------------------------
  2362                              <1> 
  2363                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2364                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2365                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2366                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2367                              <1> 
  2368                              <1> ;----------------------------------------
  2369                              <1> ;	ADDITIONAL MEDIA DATA		:
  2370                              <1> ;----------------------------------------
  2371                              <1> 
  2372                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2373                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2374                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2375                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2376                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2377                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2378                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2379                              <1> 
  2380                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2381                              <1> 
  2382                              <1> ;--------------------------------------------------------
  2383                              <1> ;	DRIVE TYPE TABLE				:
  2384                              <1> ;--------------------------------------------------------
  2385                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2386                              <1> DR_TYPE:
  2387 0000681C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2388                              <1>                 ;DW	MD_TBL1
  2389 0000681D [3A680000]          <1> 		dd	MD_TBL1
  2390 00006821 82                  <1> 		DB	02+BIT7ON
  2391                              <1> 		;DW	MD_TBL2
  2392 00006822 [47680000]          <1>                 dd      MD_TBL2
  2393 00006826 02                  <1> DR_DEFAULT:	DB	02
  2394                              <1>                 ;DW	MD_TBL3
  2395 00006827 [54680000]          <1> 		dd      MD_TBL3
  2396 0000682B 03                  <1> 		DB	03
  2397                              <1>                 ;DW	MD_TBL4
  2398 0000682C [61680000]          <1> 		dd      MD_TBL4
  2399 00006830 84                  <1> 		DB	04+BIT7ON
  2400                              <1>                 ;DW	MD_TBL5
  2401 00006831 [6E680000]          <1> 		dd      MD_TBL5
  2402 00006835 04                  <1> 		DB	04
  2403                              <1>                 ;DW	MD_TBL6
  2404 00006836 [7B680000]          <1> 		dd      MD_TBL6
  2405                              <1> DR_TYPE_E       equ $			; END OF TABLE
  2406                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2407                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2408                              <1> ;--------------------------------------------------------
  2409                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2410                              <1> ;--------------------------------------------------------
  2411                              <1> ;--------------------------------------------------------
  2412                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2413                              <1> ;--------------------------------------------------------
  2414                              <1> MD_TBL1:        
  2415 0000683A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2416 0000683B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2417 0000683C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2418 0000683D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2419 0000683E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2420 0000683F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2421 00006840 FF                  <1> 	DB	0FFH		; DTL
  2422 00006841 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2423 00006842 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2424 00006843 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2425 00006844 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2426 00006845 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2427 00006846 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2428                              <1> ;--------------------------------------------------------
  2429                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2430                              <1> ;--------------------------------------------------------
  2431                              <1> MD_TBL2:        
  2432 00006847 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2433 00006848 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2434 00006849 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2435 0000684A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2436 0000684B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2437 0000684C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2438 0000684D FF                  <1> 	DB	0FFH		; DTL
  2439 0000684E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2440 0000684F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2441 00006850 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2442 00006851 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2443 00006852 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2444 00006853 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2445                              <1> ;--------------------------------------------------------
  2446                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2447                              <1> ;--------------------------------------------------------
  2448                              <1> MD_TBL3:
  2449 00006854 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2450 00006855 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2451 00006856 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2452 00006857 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2453 00006858 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2454 00006859 1B                  <1> 	DB	01BH		; GAP LENGTH
  2455 0000685A FF                  <1> 	DB	0FFH		; DTL
  2456 0000685B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2457 0000685C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2458 0000685D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2459 0000685E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2460 0000685F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2461 00006860 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2462                              <1> ;--------------------------------------------------------
  2463                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2464                              <1> ;--------------------------------------------------------
  2465                              <1> MD_TBL4:
  2466 00006861 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2467 00006862 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2468 00006863 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2469 00006864 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2470 00006865 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2471 00006866 2A                  <1> 	DB	02AH		; GAP LENGTH
  2472 00006867 FF                  <1> 	DB	0FFH		; DTL
  2473 00006868 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2474 00006869 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2475 0000686A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2476 0000686B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2477 0000686C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2478 0000686D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2479                              <1> ;--------------------------------------------------------
  2480                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2481                              <1> ;--------------------------------------------------------
  2482                              <1> MD_TBL5:
  2483 0000686E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2484 0000686F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2485 00006870 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2486 00006871 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2487 00006872 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2488 00006873 2A                  <1> 	DB	02AH		; GAP LENGTH
  2489 00006874 FF                  <1> 	DB	0FFH		; DTL
  2490 00006875 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2491 00006876 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2492 00006877 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2493 00006878 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2494 00006879 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2495 0000687A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2496                              <1> ;--------------------------------------------------------
  2497                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2498                              <1> ;--------------------------------------------------------
  2499                              <1> MD_TBL6:
  2500 0000687B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2501 0000687C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2502 0000687D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2503 0000687E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2504 0000687F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2505 00006880 1B                  <1> 	DB	01BH		; GAP LENGTH
  2506 00006881 FF                  <1> 	DB	0FFH		; DTL
  2507 00006882 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2508 00006883 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2509 00006884 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2510 00006885 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2511 00006886 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2512 00006887 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2513                              <1> 
  2514                              <1> 
  2515                              <1> ; << diskette.inc >>
  2516                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2517                              <1> ;
  2518                              <1> ;----------------------------------------
  2519                              <1> ;	ROM BIOS DATA AREAS		:
  2520                              <1> ;----------------------------------------
  2521                              <1> 
  2522                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2523                              <1> 
  2524                              <1> ;----------------------------------------
  2525                              <1> ;	FIXED DISK DATA AREAS		:
  2526                              <1> ;----------------------------------------
  2527                              <1> 
  2528                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2529                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2530                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2531                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2532                              <1> 
  2533                              <1> ;----------------------------------------
  2534                              <1> ;	ADDITIONAL MEDIA DATA		:
  2535                              <1> ;----------------------------------------
  2536                              <1> 
  2537                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2538                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2539                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2540                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2541                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2542                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2543                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2544                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2545                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2546                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2547                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2548                              <1> 
  2549                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2550                              <1> ;
  2551                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2552                              <1> 
  2553                              <1> ERR_TBL:
  2554 00006888 E0                  <1> 	db	NO_ERR
  2555 00006889 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2556 0000688D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2557                              <1> 
  2558                              <1> ; 17/12/2014 (mov ax, [cfd])
  2559                              <1> ; 11/12/2014
  2560 00006891 00                  <1> cfd:		db	0		; current floppy drive (for GET_PARM)
  2561                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2562 00006892 01                  <1> pfd:		db	1		; previous floppy drive (for GET_PARM)
  2563                              <1> 					; (initial value of 'pfd 
  2564                              <1> 					; must be different then 'cfd' value
  2565                              <1> 					; to force updating/initializing
  2566                              <1> 					; current drive parameters) 
  2567 00006893 90                  <1> align 2
  2568                              <1> 
  2569 00006894 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2570                              <1> 			      ; (170h)
  2571 00006896 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2572                              <1> 
  2573                              <1> ; 05/01/2015 
  2574 00006898 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2575                              <1> 
  2576                              <1> ; *****************************************************************************
  2293                                  ;;;
  2294                                  
  2295 00006899 90                      Align 2
  2296                                  
  2297                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2298 0000689A 00                      boot_drv:    db 0  ; boot drive number (physical)
  2299                                  ; 24/11/2014
  2300 0000689B 00                      drv:	     db 0 
  2301 0000689C 00                      last_drv:    db 0  ; last hdd
  2302 0000689D 00                      hdc:         db 0  ; number of hard disk drives
  2303                                  		     ; (present/detected)
  2304                                  ;
  2305                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2306                                  ; Physical drive type & flags
  2307 0000689E 00                      fd0_type:    db 0  ; floppy drive type
  2308 0000689F 00                      fd1_type:    db 0    ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2309                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2310                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2311                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2312                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2313 000068A0 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2314 000068A1 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2315 000068A2 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2316 000068A3 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2317                                  		     ; bit 0 - Fixed disk access subset supported
  2318                                  		     ; bit 1 - Drive locking and ejecting
  2319                                  		     ; bit 2 - Enhanced disk drive support
  2320                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2321                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2322                                  		     ; will interpret it as 'LBA ready'!)		
  2323                                  
  2324                                  ; 11/03/2015 - 10/07/2015
  2325 000068A4 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2325 000068AD 0000000000         
  2326 000068B2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2326 000068BB 0000000000         
  2327 000068C0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2327 000068C9 0000000000         
  2328 000068CE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2328 000068D7 000000000000000000-
  2328 000068E0 000000000000000000-
  2328 000068E9 00                 
  2329 000068EA 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2330 000068F1 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2331                                  ;
  2332                                  
  2333                                  ; 27/08/2014
  2334                                  scr_row:
  2335 000068F8 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2336                                  scr_col:
  2337 000068FC 00000000                	dd 0
  2338                                  
  2339                                  ;; 14/08/2015
  2340                                  ;;msgPM:
  2341                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2342                                  msgKVER:
  2343 00006900 526574726F20554E49-     	db "Retro UNIX 386 v1.2 - Kernel v0.2.2.0 [10/01/2022]", 0
  2343 00006909 58203338362076312E-
  2343 00006912 32202D204B65726E65-
  2343 0000691B 6C2076302E322E322E-
  2343 00006924 30205B31302F30312F-
  2343 0000692D 323032325D00       
  2344                                  
  2345 00006933 90                      Align 2
  2346                                  
  2347                                  ; 20/08/2014
  2348                                    ; /* This is the default interrupt "handler" :-) */ 
  2349                                    ; Linux v0.12 (head.s)
  2350                                  int_msg:
  2351 00006934 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2351 0000693D 6E7465727275707420-
  2351 00006946 212000             
  2352                                  
  2353 00006949 90                      Align 2  
  2354                                  
  2355                                  ; 21/08/2014
  2356                                  timer_msg:
  2357 0000694A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2357 00006953 542032306829202120-
  2357 0000695C 54696D657220496E74-
  2357 00006965 657272757074203A20 
  2358                                  tcountstr:
  2359 0000696E 303030303020            	db "00000 "
  2360 00006974 00                      	db 0
  2361                                  
  2362 00006975 90                      Align 2
  2363                                  	; 21/08/2014
  2364                                  exc_msg:
  2365 00006976 435055206578636570-     	db "CPU exception ! "
  2365 0000697F 74696F6E202120     
  2366                                  excnstr: 		; 25/08/2014
  2367 00006986 3F3F68202045495020-     	db "??h", "  EIP : "
  2367 0000698F 3A20               
  2368                                  EIPstr: ; 29/08/2014
  2369 00006991 00<rep Ch>              	times 12 db 0
  2370                                  rtc_msg:
  2371 0000699D 5265616C2054696D65-     	db "Real Time Clock - "
  2371 000069A6 20436C6F636B202D20 
  2372                                  datestr:
  2373 000069AF 30302F30302F303030-     	db "00/00/0000"
  2373 000069B8 30                 
  2374 000069B9 20                      	db " "
  2375                                  daystr:
  2376 000069BA 44415920                	db "DAY "
  2377                                  timestr:	
  2378 000069BE 30303A30303A3030                db "00:00:00"
  2379 000069C6 20                      	db " "
  2380 000069C7 00                      	db 0 
  2381                                  
  2382                                  daytmp:
  2383                                  	; 28/02/2015
  2384 000069C8 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2384 000069D1 4F4E20545545205745-
  2384 000069DA 442054485520465249-
  2384 000069E3 2053415420         
  2385                                  
  2386 000069E8 FF                      ptime_seconds: db 0FFh
  2387                                  
  2388                                  	; 23/02/2015
  2389                                  	; 25/08/2014
  2390                                  ;scounter:
  2391                                  ;	db 5
  2392                                  ;	db 19
  2393                                  
  2394                                  ; 28/11/2021
  2395                                  ;; 05/11/2014
  2396                                  ;msg_out_of_memory:
  2397                                  ;	db 	07h, 0Dh, 0Ah
  2398                                  ;	db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2399                                  ; 	db	0Dh, 0Ah, 0
  2400                                  	;
  2401                                  setup_error_msg:
  2402 000069E9 0D0A                    	db 0Dh, 0Ah
  2403 000069EB 4469736B2053657475-     	db 'Disk Setup Error!' 
  2403 000069F4 70204572726F7221   
  2404 000069FC 0D0A00                  	db 0Dh, 0Ah,0
  2405                                  
  2406                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2407                                  ;crt_ulc: db 0 ; upper left column (for scroll) 
  2408                                  ;	  db 0 ; upper left row (for scroll)	
  2409                                  
  2410                                  ;crt_lrc: db 79 ; lower right column (for scroll) 
  2411                                  ;	  db 24 ; lower right row (for scroll)
  2412                                  
  2413                                  ; 06/11/2014 (Temporary Data)
  2414                                  ; Memory Information message
  2415                                  ; 14/08/2015
  2416                                  msg_memory_info:
  2417 000069FF 07                      	db	07h
  2418 00006A00 0D0A                    	db	0Dh, 0Ah
  2419                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2420 00006A02 546F74616C206D656D-     	db	"Total memory : "
  2420 00006A0B 6F7279203A20       
  2421                                  mem_total_b_str: ; 10 digits
  2422 00006A11 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2422 00006A1A 302062797465730D0A 
  2423 00006A23 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2423 00006A2C 202020202020202020 
  2424                                  mem_total_p_str: ; 7 digits
  2425 00006A35 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2425 00006A3E 616765730D0A       
  2426 00006A44 0D0A                    	db 	0Dh, 0Ah
  2427 00006A46 46726565206D656D6F-     	db	"Free memory  : "
  2427 00006A4F 727920203A20       
  2428                                  free_mem_b_str:  ; 10 digits
  2429 00006A55 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2429 00006A5E 3F2062797465730D0A 
  2430 00006A67 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2430 00006A70 202020202020202020 
  2431                                  free_mem_p_str:  ; 7 digits
  2432 00006A79 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2432 00006A82 616765730D0A       
  2433 00006A88 0D0A00                  	db	0Dh, 0Ah, 0
  2434                                  
  2435                                  dsk_ready_msg:
  2436 00006A8B 0D0A                    	db 	0Dh, 0Ah
  2437                                  dsktype:
  2438 00006A8D 6664                    	db	'fd'
  2439                                  dskx:
  2440 00006A8F 30                      	db	'0'
  2441 00006A90 20                      	db	20h
  2442 00006A91 697320524541445920-     	db 	'is READY ...'
  2442 00006A9A 2E2E2E             
  2443 00006A9D 00                      	db 	0
  2444                                  nextline:
  2445 00006A9E 0D0A00                  	db 	0Dh, 0Ah, 0
  2446                                  
  2447                                  ; KERNEL - SYSINIT Messages
  2448                                  ; 24/08/2015
  2449                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2450                                  ; 14/07/2013
  2451                                  ;kernel_init_err_msg:
  2452                                  ;	db 0Dh, 0Ah
  2453                                  ;	db 07h
  2454                                  ;	db 'Kernel initialization ERROR !'
  2455                                  ;	db 0Dh, 0Ah, 0 
  2456                                  ; 24/08/2015
  2457                                  ;;; (temporary kernel init message has been removed
  2458                                  ;;;  from 'sys_init' code)
  2459                                  ;kernel_init_ok_msg: 
  2460                                  ;	db 0Dh, 0Ah
  2461                                  ;	db 07h
  2462                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2463                                  ;	db 0Dh, 0Ah
  2464                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2465                                  ;	db 0Dh, 0Ah, 0
  2466                                  panic_msg:
  2467 00006AA1 0D0A07                  	db 0Dh, 0Ah, 07h
  2468 00006AA4 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2468 00006AAD 726E656C2050616E69-
  2468 00006AB6 632021             
  2469 00006AB9 0D0A00                  	db 0Dh, 0Ah, 0
  2470                                  etc_init_err_msg:
  2471 00006ABC 0D0A                    	db 0Dh, 0Ah
  2472 00006ABE 07                      	db 07h
  2473 00006ABF 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2473 00006AC8 74632F696E69742021-
  2473 00006AD1 3F                 
  2474 00006AD2 0D0A00                  	db 0Dh, 0Ah, 0
  2475                                  
  2476                                  ; 10/05/2015
  2477                                  badsys_msg:
  2478 00006AD5 0D0A                    	db 0Dh, 0Ah
  2479 00006AD7 07                      	db 07h
  2480 00006AD8 496E76616C69642053-     	db 'Invalid System Call !'
  2480 00006AE1 797374656D2043616C-
  2480 00006AEA 6C2021             
  2481 00006AED 0D0A                    	db 0Dh, 0Ah
  2482 00006AEF 4541583A20              	db 'EAX: '
  2483                                  bsys_msg_eax:
  2484 00006AF4 303030303030303068      	db '00000000h'
  2485 00006AFD 0D0A                    	db 0Dh, 0Ah
  2486 00006AFF 4549503A20              	db 'EIP: '
  2487                                  bsys_msg_eip:
  2488 00006B04 303030303030303068      	db '00000000h' 
  2489 00006B0D 0D0A00                  	db 0Dh, 0Ah, 0
  2490                                  
  2491                                  BSYS_M_SIZE equ $ - badsys_msg
  2492                                  
  2493                                  align 2
  2494                                  
  2495                                  ; EPOCH Variables
  2496                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2497                                  ; 09/04/2013 epoch variables
  2498                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2499                                  ;
  2500 00006B10 B207                    year: 	dw 1970
  2501 00006B12 0100                    month: 	dw 1
  2502 00006B14 0100                    day: 	dw 1
  2503 00006B16 0000                    hour: 	dw 0
  2504 00006B18 0000                    minute: dw 0
  2505 00006B1A 0000                    second: dw 0
  2506                                  
  2507                                  DMonth:
  2508 00006B1C 0000                    	dw 0
  2509 00006B1E 1F00                    	dw 31
  2510 00006B20 3B00                    	dw 59
  2511 00006B22 5A00                    	dw 90
  2512 00006B24 7800                    	dw 120
  2513 00006B26 9700                    	dw 151
  2514 00006B28 B500                    	dw 181
  2515 00006B2A D400                    	dw 212
  2516 00006B2C F300                    	dw 243
  2517 00006B2E 1101                    	dw 273
  2518 00006B30 3001                    	dw 304
  2519 00006B32 4E01                    	dw 334
  2520                                  
  2521                                  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2522                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2523 00006B34 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2524                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2525 00006B36 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2526 00006B38 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2527                                  		   ;   between 16 MB and 4 GB.
  2528 00006B3A 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2529                                  
  2530                                  ; 01/01/2022
  2531                                  KEND:
  2532                                  
  2533 00006B3C 90<rep 4h>              align 16
  2534                                  
  2535                                  bss_start:
  2536                                  
  2537                                  ABSOLUTE bss_start
  2538                                  
  2539                                  	; 11/03/2015
  2540                                  	; Interrupt Descriptor Table (20/08/2014)
  2541                                  idt:
  2542 00006B40 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2543                                  idt_end:
  2544                                  
  2545                                  ;alignb 4
  2546                                  
  2547                                  task_state_segment:
  2548                                  	; 24/03/2015
  2549 00006D40 ????                    tss.link:   resw 1
  2550 00006D42 ????                    	    resw 1
  2551                                  ; tss offset 4	
  2552 00006D44 ????????                tss.esp0:   resd 1
  2553 00006D48 ????                    tss.ss0:    resw 1
  2554 00006D4A ????                    	    resw 1	
  2555 00006D4C ????????                tss.esp1:   resd 1
  2556 00006D50 ????                    tss.ss1:    resw 1
  2557 00006D52 ????                    	    resw 1 	
  2558 00006D54 ????????                tss.esp2:   resd 1
  2559 00006D58 ????                    tss.ss2:    resw 1
  2560 00006D5A ????                    	    resw 1
  2561                                  ; tss offset 28
  2562 00006D5C ????????                tss.CR3:    resd 1
  2563 00006D60 ????????                tss.eip:    resd 1
  2564 00006D64 ????????                tss.eflags: resd 1
  2565                                  ; tss offset 40
  2566 00006D68 ????????                tss.eax:    resd 1		 		
  2567 00006D6C ????????                tss.ecx:    resd 1
  2568 00006D70 ????????                tss.edx:    resd 1
  2569 00006D74 ????????                tss.ebx:    resd 1
  2570 00006D78 ????????                tss.esp:    resd 1
  2571 00006D7C ????????                tss.ebp:    resd 1
  2572 00006D80 ????????                tss.esi:    resd 1
  2573 00006D84 ????????                tss.edi:    resd 1
  2574                                  ; tss offset 72
  2575 00006D88 ????                    tss.ES:     resw 1
  2576 00006D8A ????                    	    resw 1	
  2577 00006D8C ????                    tss.CS:	    resw 1
  2578 00006D8E ????                    	    resw 1
  2579 00006D90 ????                    tss.SS:	    resw 1
  2580 00006D92 ????                    	    resw 1
  2581 00006D94 ????                    tss.DS:	    resw 1
  2582 00006D96 ????                    	    resw 1
  2583 00006D98 ????                    tss.FS:	    resw 1
  2584 00006D9A ????                    	    resw 1
  2585 00006D9C ????                    tss.GS:	    resw 1
  2586 00006D9E ????                    	    resw 1		
  2587 00006DA0 ????                    tss.LDTR:   resw 1
  2588 00006DA2 ????                    	    resw 1
  2589                                  ; tss offset 100		
  2590 00006DA4 ????                    	    resw 1		
  2591 00006DA6 ????                    tss.IOPB:   resw 1
  2592                                  ; tss offset 104 
  2593                                  tss_end:
  2594                                  
  2595 00006DA8 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2596                                  		    ;  (Physical address = Virtual address)	 	
  2597 00006DAC ????????                memory_size: resd 1 ; memory size in pages
  2598 00006DB0 ????????                free_pages:  resd 1 ; number of free pages		
  2599 00006DB4 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2600                                  		    ;   first free page search
  2601 00006DB8 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2602                                  		    ;   next free page search will be
  2603                                  		    ;   stopped after it. (end of M.A.T.)
  2604 00006DBC ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2605                                  		    ; first free page search
  2606                                  		    ;   will be started on it. (for user)
  2607 00006DC0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2608                                  
  2609                                  ;;;
  2610                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2611                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2612 00006DC4 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2613                                  			  ; NOTE: active page only
  2614 00006DC6 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2615                                  active_page: 
  2616 00006DD6 ??                      ptty: 	     resb 1 	  ; current tty
  2617                                  ; 01/07/2015
  2618 00006DD7 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2619                                  ; 26/10/2015
  2620                                  ; 07/09/2014
  2621 00006DD8 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2622                                  
  2623                                  ; 21/08/2014
  2624 00006DEC ????????                tcount:	     resd 1
  2625                                  
  2626                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2627 00006DF0 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2628                                  
  2629                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2630                                  ; (open mode locks for pseudo TTYs)
  2631                                  ; [ major tty locks (return error in any conflicts) ]
  2632 00006DF4 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2633                                  
  2634                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2635                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2636 00006E08 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2637                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2638                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2639                                  ;; 0 means serial port is not available 
  2640                                  ;;comprm: ; 25/06/2014
  2641 00006E12 ??                      com1p:       resb 1  ;;0E3h
  2642 00006E13 ??                      com2p:       resb 1  ;;0E3h
  2643                                  
  2644                                  ; 17/11/2015
  2645                                  ; request for response (from the terminal)	
  2646 00006E14 ????                    req_resp:    resw 1 			
  2647                                  ; 07/11/2015
  2648 00006E16 ??                      ccomport:    resb 1 ; current COM (serial) port
  2649                                  		    ; (0= COM1, 1= COM2)
  2650                                  ; 09/11/2015
  2651 00006E17 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2652                                  ; 07/11/2015
  2653 00006E18 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2654 00006E1A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2655                                  
  2656                                  ; 23/10/2015
  2657                                  ; SERIAL PORTS - COMMUNICATION MODES
  2658                                  ; (Retro UNIX 386 v1 feature only!)
  2659                                  ; 0 - command mode (default/initial mode)
  2660                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2661                                  ;;; communication modes for futre versions:  
  2662                                  ; // 2 - keyboard mode (ascii+scancode input)
  2663                                  ; // 3 - mouse mode
  2664                                  ; // 4 - device control (output) mode
  2665                                  ; VALID COMMANDS for current version:
  2666                                  ; 	'LOGIN'
  2667                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2668                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2669                                  ;  Login response: db 0FFh, 'login', 0
  2670                                  ;	 ("login request accepted, wait for login prompt") 
  2671                                  ; When a login requests is received and acknowledged (by
  2672                                  ; serial port interrupt handler (communication procedure),
  2673                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2674                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2675                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2676                                  ; 
  2677                                  ; 'sys connect' system call is used to change communication mode
  2678                                  ; except 'LOGIN' command which is used to start terminal mode
  2679                                  ; by using (COM port) terminal.
  2680                                  
  2681                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2682                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2683                                  ;com1mode:    resb 1 ; communication mode for COM1
  2684                                  ;com1com:     resb 1 ; communication command for COM1
  2685                                  ;com2mode:    resb 1 ; communication mode for COM1
  2686                                  ;com2com      resb 1 ; communication command for COM1
  2687                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2688                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2689                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2690                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2691                                  
  2692                                  ; 22/08/2014 (RTC)
  2693                                  ; (Packed BCD)
  2694 00006E1C ??                      time_seconds: resb 1
  2695 00006E1D ??                      time_minutes: resb 1
  2696 00006E1E ??                      time_hours:   resb 1
  2697 00006E1F ??                      date_wday:    resb 1
  2698 00006E20 ??                      date_day:     resb 1
  2699 00006E21 ??                      date_month:   resb 1			
  2700 00006E22 ??                      date_year:    resb 1
  2701 00006E23 ??                      date_century: resb 1
  2702                                  
  2703                                  %include 'diskbss.s'	; UNINITIALIZED DISK (BIOS) DATA
  2704                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2705                              <1> ; Last Modification: 10/07/2015
  2706                              <1> ;	(Unitialized Disk Parameters Data section for 'DISKIO.INC') 
  2707                              <1> ;
  2708                              <1> ; *****************************************************************************
  2709                              <1> 
  2710                              <1> alignb 2
  2711                              <1> 
  2712                              <1> ;----------------------------------------
  2713                              <1> ;	TIMER DATA AREA 		:
  2714                              <1> ;----------------------------------------
  2715                              <1> 
  2716                              <1> TIMER_LH:	; 16/02/2015
  2717 00006E24 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2718 00006E26 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2719 00006E28 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2720                              <1> 
  2721                              <1> ;----------------------------------------
  2722                              <1> ;	DISKETTE DATA AREAS		:
  2723                              <1> ;----------------------------------------
  2724                              <1> 
  2725 00006E29 ??                  <1> SEEK_STATUS:	resb	1
  2726 00006E2A ??                  <1> MOTOR_STATUS:	resb	1
  2727 00006E2B ??                  <1> MOTOR_COUNT:	resb	1
  2728 00006E2C ??                  <1> DSKETTE_STATUS:	resb	1
  2729 00006E2D ??????????????      <1> NEC_STATUS:	resb	7
  2730                              <1> 
  2731                              <1> ;----------------------------------------
  2732                              <1> ;	ADDITIONAL MEDIA DATA		:
  2733                              <1> ;----------------------------------------
  2734                              <1> 
  2735 00006E34 ??                  <1> LASTRATE:	resb 	1
  2736 00006E35 ??                  <1> HF_STATUS:	resb 	1
  2737 00006E36 ??                  <1> HF_ERROR:	resb 	1
  2738 00006E37 ??                  <1> HF_INT_FLAG:	resb 	1
  2739 00006E38 ??                  <1> HF_CNTRL:	resb 	1
  2740 00006E39 ????????            <1> DSK_STATE:	resb 	4
  2741 00006E3D ????                <1> DSK_TRK:	resb 	2
  2742                              <1> 
  2743                              <1> ;----------------------------------------
  2744                              <1> ;	FIXED DISK DATA AREAS		:
  2745                              <1> ;----------------------------------------
  2746                              <1> 
  2747 00006E3F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2748 00006E40 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2749 00006E41 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2750                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2751                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2752                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2753                              <1> 
  2754 00006E42 ????                <1> alignb 4
  2755                              <1> 
  2756                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2757                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2758                              <1> HF_TBL_VEC: ; 22/12/2014	
  2759 00006E44 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2760 00006E48 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2761 00006E4C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2762 00006E50 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2763                              <1> 
  2764                              <1> ; 03/01/2015
  2765 00006E54 ??                  <1> LBAMode:     	resb	1
  2766                              <1> 
  2767                              <1> ; *****************************************************************************
  2704                                  
  2705                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2706                                  
  2707                                  ;alignb 2
  2708                                  
  2709                                  ; 02/01/2022
  2710                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2711                                  
  2712                                  ; 17/04/2021
  2713                                  ; (memory page swap parameters are disabled as temporary)
  2714                                  ;
  2715                                  ;; Memory (swap) Data (11/03/2015)
  2716                                  ; 09/03/2015
  2717                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2718                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2719                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2720                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2721                                  ;swpd_next:  resd 1 ; next free page block
  2722                                  ;swpd_last:  resd 1 ; last swap page block	
  2723                                  
  2724 00006E55 ??????                  alignb 4
  2725                                  
  2726                                  ; 10/07/2015
  2727                                  ; 28/08/2014
  2728 00006E58 ????????                error_code:	resd 1
  2729                                  ; 29/08/2014
  2730 00006E5C ????????                FaultOffset:	resd 1
  2731                                  ; 21/09/2015
  2732 00006E60 ????????                PF_Count:	resd 1	; total page fault count
  2733                                  		       	; (for debugging - page fault analyze)
  2734                                  		 	; 'page _fault_handler' (memory.s)
  2735                                  			; 'sysgeterr' (u9.s)
  2736                                  ;; 21/08/2015
  2737                                  ;;buffer: resb (nbuf*520) ;; sysdefs.s, ux.s
  2738                                  
  2739                                  ; 02/01/2022
  2740                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2741                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2742                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2743                              <1> ; ****************************************************************************
  2744                              <1> ; Retro UNIX 386 v1.2 Kernel - ux.s
  2745                              <1> ; Last Modification: 10/01/2022
  2746                              <1> ;
  2747                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2748                              <1> ; (Modified from 
  2749                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2750                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2751                              <1> ; ----------------------------------------------------------------------------
  2752                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2753                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2754                              <1> ; <Bell Laboratories (17/3/1972)>
  2755                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2756                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2757                              <1> ; ****************************************************************************
  2758                              <1> 
  2759                              <1> ; 22/11/2021 (Modification in Runix v1.1 'ux.s' for runix v2 fs compatibility)
  2760                              <1> ; 18/07/2021
  2761                              <1> ; 15/07/2021
  2762                              <1> ; 12/05/2021
  2763                              <1> ; 09/05/2021
  2764                              <1> ; 06/05/2021
  2765                              <1> ; 02/05/2021
  2766                              <1> ; 26/01/2020 (NASM version of SuperBlock structure in UNIXHDCP.ASM)
  2767                              <1> 
  2768                              <1> ; 21/12/2019 (UNIXCOPY.COM, UNIXCOPY.ASM, UNIXHDCP.COM, UNIXHDCP.ASM)
  2769                              <1> ; 19/12/2019 (UNIXHDFS.COM, RUFSHDI.ASM)
  2770                              <1> ; 01/09/2019 - Retro UNIX 386 v2 SuperBlock
  2771                              <1> 
  2772                              <1> ; 14/01/2020 - Super Block modification:
  2773                              <1> ;	     - Extended sections/divisions (consequental sectors)
  2774                              <1> ;	     - (for swapping, configuration, boot space etc.)	
  2775                              <1> 
  2776                              <1> struc SB ; SuperBlock
  2777                              <1> 
  2778 00000000 ????????            <1> .Header:	resd 1
  2779                              <1> ;.HiddenSects:
  2780 00000004 ????????            <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2781                              <1> ;.TotalSects:
  2782 00000008 ????????            <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)	
  2783 0000000C ????????            <1> .Version:	resd 1	
  2784 00000010 ????????            <1> .BlockSize:	resd 1	
  2785 00000014 ????????            <1> .InodeCount:	resd 1		
  2786 00000018 ????????            <1> .FreeMapAddr:	resd 1	
  2787 0000001C ????????            <1> .FreeMapSize:	resd 1	
  2788 00000020 ????????            <1> .InodeMapAddr:	resd 1	
  2789 00000024 ????????            <1> .InodeMapSize:	resd 1	
  2790 00000028 ????????            <1> .InodeTblAddr:	resd 1	
  2791 0000002C ????????            <1> .InodeTblSize:	resd 1	
  2792 00000030 ????????            <1> .FreeInodes:	resd 1	
  2793 00000034 ????????            <1> .FirstFreeIno:	resd 1	
  2794 00000038 ????????            <1> .FreeBlocks:	resd 1	
  2795 0000003C ????????            <1> .FirstFreeBlk:	resd 1	
  2796 00000040 <res 13h>           <1> .BootSecParms:	resb 19	; v1
  2797 00000053 ??????????          <1> .BSExtension:	resb 5	; v2 HDFS
  2798 00000058 ??                  <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2799 00000059 ??                  <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2800 0000005A ????                <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2801 0000005C ????????            <1> .ModifTime:	resd 1	; (last) modification time (*)
  2802 00000060 ????????            <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2803 00000064 ????????            <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2804 00000068 ??                  <1> .LBA_rw:	resb 1
  2805 00000069 ??                  <1> .ClusterSize:	resb 1
  2806 0000006A ??                  <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2807 0000006B ??                  <1> .Mounted:	resb 1
  2808 0000006C ????????            <1> .MountInode:	resd 1  ; double word
  2809 00000070 ??                  <1> .DevMajor:	resb 1
  2810 00000071 ??                  <1> .DevMinor:	resb 1
  2811 00000072 ??                  <1> .LongName:	resb 1
  2812 00000073 ??                  <1> .Direntry32:	resb 1
  2813                              <1> ; 18/07/2021
  2814 00000074 ????????            <1> .FileBuffer:	resd 1
  2815 00000078 ????????            <1> .ItabBuffer:	resd 1
  2816 0000007C ????????            <1> .ImapBuffer:	resd 1
  2817 00000080 ????????            <1> .FmapBuffer:	resd 1
  2818                              <1>  ; 15/07/2021
  2819 00000084 ????????            <1> .LastInode:	resd 1
  2820                              <1> ; 02/05/2021
  2821 00000088 ????????            <1> .FmapIndex:	resd 1
  2822 0000008C ????????            <1> .ImapIndex:	resd 1
  2823 00000090 ????????            <1> .ItableIndex:	resd 1
  2824 00000094 <res 168h>          <1> .Reserved:	resb 508-148 ; 18/07/2021
  2825 000001FC ????????            <1> .Footer:	resd 1
  2826                              <1> 
  2827                              <1> endstruc
  2828                              <1> 
  2829                              <1> ; 26/01/2020 (unix386.s, ux.s)
  2830                              <1> ; 14/01/2020
  2831                              <1> SB.HiddenSects	equ SB.BootSectAddr
  2832                              <1> SB.TotalSects	equ SB.VolumeSize
  2833                              <1> 
  2834                              <1> ; 11/05/2021 (Retro UNIX 386 v2)
  2835                              <1> ; Super block status byte (byte 0 of SB.status dword)
  2836                              <1> ; 	bit 0 - superblock modified flag
  2837                              <1> ; 	bit 1 - inode map modified flag
  2838                              <1> ; 	bit 2 - free blocks map modified flag
  2839                              <1> ; 	bit 3 - inode table modified flag
  2840                              <1> ;; 	bit 4 - boot sector modified flag ; 17/08/2021
  2841                              <1> ; 17/08/2021
  2842                              <1> ;	bit 4 - file data write error (for SB.LastInode)
  2843                              <1> ;	bit 5 - inode table write error (for SB.LastInode)
  2844                              <1> ;	bit 6 - inode map write error (for SB.LastInode)
  2845                              <1> ;	bit 7 - free blocks map write error (for SB.LastInode)
  2846                              <1> 	
  2847                              <1> ; 21/12/2019
  2848                              <1> ; 19/12/2019 - Retro UNIX 386 v2 HD (071h) partition boot sector 
  2849                              <1> ;	       (UNIXHDFS.ASM)
  2850                              <1> ; 04/12/2015 (14 byte file names - Retro UNIX 386 v1.1)
  2851                              <1> ; 14/07/2015 (8 byte file names - Retro UNIX 8086 v1 & Retro UNIX 386 v1.0)
  2852                              <1> 
  2853                              <1> bsFSystemID 	equ 2  ; db 'RUFS'	
  2854                              <1> bsVolumeSerial 	equ 6  ; dd 0 ; (4 bytes)
  2855                              <1> bsFDSign	equ 10 ; db 'fd'
  2856                              <1> bsDriveNumber 	equ 12 ; db 0 ; fd0 or fd1 (0 or 1)
  2857                              <1> bsReserved 	equ 13 ; db 0 ; (512 bytes per sector)	
  2858                              <1> bsSecPerTrack	equ 14 ; db 18 ; (9 or 15)	
  2859                              <1> bsHeads		equ 15 ; db  ; 2
  2860                              <1> bsTracks	equ 16 ; dw 80 ; bsCylinders
  2861                              <1> bs_bf_inode_number equ 18 ; dw 0 ; 0 or Boot/Startup File I-Number
  2862                              <1> bsInfoEndsign	equ 20 ; db '@'
  2863                              <1> ; 21/12/2019
  2864                              <1> bsMagic		equ 20 ; db '@'
  2865                              <1> bsPartitionID	equ 21 ; db 0 ; db 71h
  2866                              <1> bsHiddenSects	equ 22 ; dd 0 ; Hidden sectors (Boot Sector LBA)
  2867                              <1> 
  2868                              <1> ; 22/11/2021 - Retro UNIX v2 I-node Flags
  2869                              <1> ; ------------------------------------------------------------------
  2870                              <1> ; UINSTALL.ASM (included in UNIXFDFS.ASM) - 23/01/2020
  2871                              <1> ; ------------------------------------------------------------------
  2872                              <1> 
  2873                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  2874                              <1> ; 1000000000000000b 	IFREG - 1 = regular file (8000h)
  2875                              <1> ; 0100000000000000b	IFDIR - 1 = directory (4000h)
  2876                              <1> ; 0010000000000000b	IRSVD - 0 = reserved bit (2000h) ; Mounted flag
  2877                              <1> ; 0001000000000000b	ILARG - large file addressing bit (1000h)
  2878                              <1> ; 0000100000000000b	ISUID - set user id on exec (800h)
  2879                              <1> ; 0000010000000000b	ISGID - set group id on exec (400h)
  2880                              <1> ; 0000001000000000b	IEXTT - 1 = use extents (200h)
  2881                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2882                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2883                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2884                              <1> ; 0000000000100000b	read, group (20h)
  2885                              <1> ; 0000000000010000b	write, group (10h)
  2886                              <1> ; 0000000000001000b	execute, group (08h)
  2887                              <1> ; 0000000000000100b	read, others (04h)
  2888                              <1> ; 0000000000000010b	write, others (02h)
  2889                              <1> ; 0000000000000001b	execute, others (01h)
  2890                              <1> 
  2891                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  2892                              <1> ; 1000000000000000b 	IFREG - 0 = device file (8000h)
  2893                              <1> ; 0100000000000000b	IFBLK - 1 = block device (4000h)
  2894                              <1> ; 0010000000000000b	IFCHR - character special (2000h) -always 1-
  2895                              <1> ; 0001000000000000b	IFIFO - fifo special (1000h)
  2896                              <1> ; 0000100000000000b	IPIPE - pipe special (800h) ; 07/02/2020
  2897                              <1> ; 0000010000000000b	IREDIR - redirected (400h)  ; 07/02/2020
  2898                              <1> ; 0000001000000000b	IEXTR - 1 = external device driver (200h)
  2899                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2900                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2901                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2902                              <1> ; 0000000000100000b	read, group (20h)
  2903                              <1> ; 0000000000010000b	write, group (10h)
  2904                              <1> ; 0000000000001000b	execute, group (08h)
  2905                              <1> ; 0000000000000100b	read, others (04h)
  2906                              <1> ; 0000000000000010b	write, others (02h)
  2907                              <1> ; 0000000000000001b	execute, others (01h)
  2908                              <1> 
  2909                              <1> alignb 2
  2910                              <1> 
  2911                              <1> inode:
  2912                              <1> 	;; 11/03/2013. 
  2913                              <1> 	;;Derived from UNIX v1 source code 'inode' structure (ux).
  2914                              <1> 	;;i.
  2915                              <1> 	;
  2916                              <1> 	;i.flgs: resw 1
  2917                              <1> 	;i.nlks: resb 1
  2918                              <1> 	;i.uid:	 resb 1
  2919                              <1>         ;i.size: resw 1 ; size
  2920                              <1> 	;i.dskp: resw 8 ; 16 bytes
  2921                              <1> 	;i.ctim: resd 1
  2922                              <1> 	;i.mtim: resd 1
  2923                              <1> 	;i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1)
  2924                              <1> 
  2925                              <1> 	; 26/01/2020
  2926                              <1> 	; Retro UNIX 386 v2.0 - Modified UNIX v7 inode model
  2927                              <1> 	;	(15/09/2029 .. 18/12/2019)
  2928                              <1> 
  2929 00006B40 ????                <1> 	i.flgs:   resw 1	; /* mode and type of file */
  2930 00006B42 ????                <1> 	i.nlks:	  resw 1	; /* number of links to file */
  2931 00006B44 ????                <1> 	i.uid:	  resw 1	; /* owner's user id */  - 0 to 655535 -
  2932 00006B46 ??                  <1> 	i.gid:	  resb 1	; /* owner's group id */ - o to 255 -
  2933 00006B47 ??                  <1> 	i.size_h: resb 1	; /* number of bytes in file */ ; byte 5
  2934 00006B48 ????????            <1> 	i.size:	  resd 1 ; size	; /* number of bytes in file */
  2935 00006B4C <res 28h>           <1> 	i.dskp:	  resd 10 ; 40 bytes ; /* disk block addresses */
  2936 00006B74 ????????            <1> 	i.atim:	  resd 1	; /* time last accessed */
  2937 00006B78 ????????            <1> 	i.mtim:	  resd 1	; /* time last modified */
  2938 00006B7C ????????            <1> 	i.ctim:	  resd 1	; /* time created */
  2939                              <1> 
  2940                              <1> I_SIZE	equ $ - inode
  2941                              <1> 
  2942                              <1> process:
  2943                              <1> 	; 06/05/2015
  2944                              <1> 	; 11/03/2013 - 05/02/2014
  2945                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2946                              <1> 	;p.
  2947                              <1> 	
  2948 00006B80 <res 20h>           <1>         p.pid:   resw nproc
  2949 00006BA0 <res 20h>           <1>         p.ppid:  resw nproc
  2950 00006BC0 <res 20h>           <1>         p.break: resw nproc
  2951 00006BE0 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2952 00006BF0 <res 10h>           <1> 	p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2953 00006C00 <res 10h>           <1> 	p.link:	 resb nproc
  2954 00006C10 <res 10h>           <1> 	p.stat:	 resb nproc
  2955                              <1> 
  2956                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 feature only !) 
  2957 00006C20 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2958                              <1> 			    ; 'user' structure	
  2959                              <1> 
  2960                              <1> P_SIZE	equ $ - process
  2961                              <1> 
  2962                              <1> ; fsp table (original UNIX v1)
  2963                              <1> ;
  2964                              <1> ;Entry
  2965                              <1> ;          15                                      0
  2966                              <1> ;  1     |---|---------------------------------------|
  2967                              <1> ;        |r/w|       i-number of open file           |
  2968                              <1> ;        |---|---------------------------------------| 
  2969                              <1> ;        |               device number               |
  2970                              <1> ;        |-------------------------------------------|
  2971                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2972                              <1> ;        |-------------------------------------------| 
  2973                              <1> ;        |  flag that says    | number of processes  |
  2974                              <1> ;        |   file deleted     | that have file open  |
  2975                              <1> ;        |-------------------------------------------| 
  2976                              <1> ;  2     |                                           |
  2977                              <1> ;        |-------------------------------------------| 
  2978                              <1> ;        |                                           |
  2979                              <1> ;        |-------------------------------------------|
  2980                              <1> ;        |                                           |
  2981                              <1> ;        |-------------------------------------------|
  2982                              <1> ;        |                                           |
  2983                              <1> ;        |-------------------------------------------| 
  2984                              <1> ;  3     |                                           | 
  2985                              <1> ;        |                                           |  
  2986                              <1> ;
  2987                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2988                              <1> 
  2989                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  2990                              <1> 
  2991                              <1> ;Entry
  2992                              <1> ;         15                    7                   0
  2993                              <1> ;  1     |-------------------------------------------|
  2994                              <1> ;        |   	     i-number of open file           |
  2995                              <1> ;        |-------------------------------------------| 
  2996                              <1> ;        |        high word of 32 bit i-number       |
  2997                              <1> ;        |-------------------------------------------|
  2998                              <1> ;        | open mode & status  |   device number     |
  2999                              <1> ;        |-------------------------------------------|
  3000                              <1> ;        |    reserved byte    |     open count      |
  3001                              <1> ;        |-------------------------------------------| 
  3002                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3003                              <1> ;        |-------------------------------------------|
  3004                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3005                              <1> ;        |-------------------------------------------|
  3006                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3007                              <1> ;        |-------------------------------------------|
  3008                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3009                              <1> ;        |-------------------------------------------|
  3010                              <1> ;  2     |                                           |
  3011                              <1> ;        |-------------------------------------------| 
  3012                              <1> ;        |                                           |
  3013                              <1> ;        |-------------------------------------------|
  3014                              <1> ;        |                                           |
  3015                              <1> ;        |-------------------------------------------|
  3016                              <1> ;        |                                           |
  3017                              <1> ;        |-------------------------------------------| 
  3018                              <1> ;        |                                           | 
  3019                              <1> 
  3020                              <1> ; 22/11/2021
  3021                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision
  3022                              <1> 
  3023                              <1> struc file	; open files (fsp) structure
  3024 00000000 ????                <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  3025 00000002 ????                <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  3026 00000004 ??                  <1>   .drive:  resb 1  ; logical drive (disk) number
  3027 00000005 ??                  <1>   .flags:  resb 1  ; open mode and status
  3028 00000006 ??                  <1>   .count:  resb 1  ; number of processes that have file open
  3029                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  3030 00000007 ??                  <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  3031 00000008 ????????            <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  3032 0000000C ????????            <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  3033                              <1>  .size:  ; = 16		
  3034                              <1> endstruc
  3035                              <1> 
  3036                              <1> ; 01/01/2022
  3037                              <1> ; 22/11/2021
  3038                              <1> ;fp.size equ file.size
  3039                              <1> 
  3040                              <1> ; 02/01/2022
  3041 00006B40 <res 320h>          <1> fsp:	resb nfiles*16 ; (NFILES*fp.size)
  3042                              <1> ; 01/01/2022
  3043                              <1> ; 22/11/2021 (16/05/2021)
  3044                              <1> ;fsp:	resb NFILES*16 ; (NFILES*fp.size)
  3045                              <1> ; 15/04/2015
  3046                              <1> ;fsp:	resb nfiles*10 ; 11/05/2015 (8 -> 10)
  3047                              <1> 
  3048 00006E60 <res 20h>           <1> bufp:	resd (nbuf+2) ; will be initialized 
  3049 00006E80 ????????            <1> ii:	resd 1 ; 22/11/2021 ; 32 bit inode number (high word is 0)
  3050                              <1> ; 22/11/2021
  3051 00006E84 ??                  <1> idev:	resb 1 ; logical drive number of current inode, [ii]
  3052 00006E85 ??                  <1> cdev:	resb 1 ; current logical drive number for current user
  3053                              <1> 
  3054                              <1> ; 18/05/2015
  3055                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  3056                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  3057                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  3058                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  3059                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  3060                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  3061                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  3062                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  3063                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  3064                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  3065                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  3066 00006E86 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  3067                              <1> 	        ; as above, for physical drives numbers in following table
  3068 00006E87 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  3069                              <1> ; 15/04/2015
  3070 00006E88 ??                  <1> active:	 resb 1 
  3071 00006E89 ??                  <1> 	 resb 1 ; 09/06/2015
  3072 00006E8A ????                <1> mpid:	 resw 1
  3073                              <1> ; 22/11/2021 (32 bit inode numbers)
  3074 00006E8C ????????            <1> rootdir: resd 1
  3075 00006E90 ????????            <1> mnti:	 resd 1
  3076                              <1> 
  3077                              <1> ; 14/02/2014
  3078                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  3079                              <1> ;		      Single level run queue
  3080                              <1> ;		      (in order to solve sleep/wakeup lock)
  3081 00006E94 ????                <1> runq:	resw 1
  3082 00006E96 ??                  <1> imod:	resb 1
  3083 00006E97 ??                  <1> imodx:	resb 1 ; 09/01/2022 - Retro UNIX 386 v1.2
  3084 00006E98 ??                  <1> smod:	resb 1
  3085 00006E99 ??                  <1> mmod:	resb 1
  3086                              <1> ;	resb 1 ; 09/01/2022 
  3087 00006E9A ??                  <1> sysflg:	resb 1
  3088                              <1> 
  3089 00006E9B ??                  <1> alignb 4
  3090                              <1> 
  3091                              <1> user:
  3092                              <1> 	; 01/01/2022
  3093                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3094                              <1> 	; 24/10/2021
  3095                              <1> 	; 18/10/2021
  3096                              <1> 	; 10/06/2021
  3097                              <1> 	; 30/05/2021
  3098                              <1> 	; 29/05/2021
  3099                              <1> 	; 21/05/2021
  3100                              <1> 	; 20/05/2021
  3101                              <1> 	; 16/05/2021
  3102                              <1> 	; 01/05/2021
  3103                              <1> 	; 27/03/2021
  3104                              <1> 	; 17/04/2020, 28/04/2020
  3105                              <1> 	; 25/03/2020, 28/03/2020
  3106                              <1> 	; 20/03/2020, 22/03/2020, 23/03/2020
  3107                              <1> 	; 05/03/2020, 08/03/2020, 14/03/2020
  3108                              <1> 	; 07/02/2020 - Retro UNIX 386 v2
  3109                              <1> 	;
  3110                              <1> 	; 27/02/2017 - TRDOS 386
  3111                              <1> 	; 13/01/2017 - TRDOS 386
  3112                              <1> 	; 10/01/2017 - TRDOS 386
  3113                              <1> 	; 19/12/2016 - TRDOS 386	
  3114                              <1> 	; 21/05/2016 - TRDOS 386 (TRDOS v2.0) 
  3115                              <1> 	; 	       [u.pri] usage method modification
  3116                              <1> 	;
  3117                              <1> 	; 04/12/2015 - Retro UNIX 386 v1.1 (14 byte file/directory names)
  3118                              <1> 	; 18/10/2015
  3119                              <1> 	; 12/10/2015
  3120                              <1> 	; 21/09/2015
  3121                              <1> 	; 24/07/2015
  3122                              <1> 	; 16/06/2015
  3123                              <1> 	; 09/06/2015
  3124                              <1> 	; 11/05/2015
  3125                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  3126                              <1> 	; 10/10/2013
  3127                              <1> 	; 11/03/2013. 
  3128                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  3129                              <1> 	;u.
  3130                              <1> 
  3131 00006E9C ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  3132 00006EA0 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  3133 00006EA4 ????????            <1> 	u.r0:	  resd 1 ; eax
  3134 00006EA8 ????                <1> 	u.cdir:	  resw 1
  3135 00006EAA ????                <1> 		  resw 1 ; 28/03/2020 - reserved for 32 bit inode number
  3136                              <1> 	;u.cdrv:  resw 1 ; 17/04/2020 (dword alignment) 
  3137 00006EAC ??                  <1> 	u.cdrv:   resb 1 ; 01/05/2021
  3138 00006EAD ??                  <1> 		  resb 1 ; 01/05/2021 (dword alignment)
  3139 00006EAE <res Ah>            <1> 	u.fp:	  resb 10 ; Retro UNIX 386 v1
  3140                              <1> 	;u.fp:	  resb OPENFILES ; Retro UNIX 386 v2 ; 28/03/2020 
  3141                              <1> 	u.fsp:	  ; 16/05/2021
  3142 00006EB8 ????????            <1> 	u.fofp:	  resd 1 ; 16/05/2021 (pointer to fsp entry)
  3143 00006EBC ????????            <1> 	u.dirp:	  resd 1
  3144 00006EC0 ????????            <1> 	u.namep:  resd 1
  3145 00006EC4 ????????            <1> 	u.off:	  resd 1
  3146                              <1> ;		  resd 1 ; 08/03/2020 - Retro UNIX 386 v2 - 64 bit fptr
  3147 00006EC8 ????????            <1> 	u.base:	  resd 1
  3148 00006ECC ????????            <1> 	u.count:  resd 1
  3149 00006ED0 ????????            <1> 	u.nread:  resd 1
  3150 00006ED4 ????????            <1> 	u.break:  resd 1 ; break
  3151                              <1> 	; 16/05/2021 (Retro UNIX 386 v2)
  3152 00006ED8 ??                  <1> 	u.mode:   resb 1 ; 16/05/2021 (sysread, syswrite, 'rdwr' file mode)
  3153                              <1> 	; 10/01/2017 (TRDOS 386, relocation and dword alignment)
  3154                              <1> 	; tty number (rtty, rcvt, wtty)
  3155 00006ED9 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  3156 00006EDA ????                <1> 	u.ttyp:	  resw 1 
  3157 00006EDC <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  3158                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  3159 00006EEC ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  3160 00006EED ??                  <1> 		  resb 1 ; 17/04/2020
  3161 00006EEE ??                  <1> 	u.pri:	  resb 1 ; Modification: 21/05/2016 (priority levels: 0, 1, 2)
  3162 00006EEF ??                  <1> 		  resb 1 ; 17/04/2020
  3163                              <1> 	; 10/06/2021
  3164                              <1> 	;u.signal: resw 1 ; 21/05/2021 - Retro UNIX 386 v2
  3165                              <1> 	;	  resw 1 ; reserved ; 21/05/2021	
  3166 00006EF0 ????                <1> 	u.intr:	  resw 1
  3167 00006EF2 ????                <1> 	u.quit:	  resw 1
  3168                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  3169                              <1> 	;u.ilgins: resw 1 ; 10/01/2017
  3170                              <1> 	;u.cdrv:  resw 1 ; cdev ; 17/04/2020 (moved to up)
  3171                              <1> 	;u.uid:	  resb 1 ; uid
  3172                              <1> 	;u.ruid:  resb 1
  3173 00006EF4 ??                  <1> 	u.bsys:	  resb 1
  3174 00006EF5 ??                  <1> 	u.uno:	  resb 1
  3175 00006EF6 ????                <1>         u.uid:	  resw 1 ; uid	; 27/03/2021 - Retro UNIX 386 v2
  3176 00006EF8 ????                <1> 	u.ruid:	  resw 1	; 16 bit uid
  3177 00006EFA ??                  <1> 	u.gid:	  resb 1 ; gid 	; 27/03/2021 - Retro UNIX 386 v2
  3178 00006EFB ??                  <1> 	u.rgid:	  resb 1
  3179                              <1> 	; 20/05/2021 - Retro UNIX 386 v2
  3180 00006EFC ????????            <1> 	u.procp:  resd 1 ; /* pointer to proc structure */		
  3181 00006F00 ????????            <1> 	u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  3182 00006F04 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  3183 00006F08 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  3184 00006F0C ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  3185                              <1> 		; 24/10/2021 (32 bit value for Retro UNIX 386 v2)
  3186 00006F10 ????????            <1> 	u.pcount: resd 1 ; 20/05/2015 (byte -transfer- count for page)
  3187                              <1> 	;u.pncount: resw 1 
  3188                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  3189                              <1> 	;u.pnbase:  resd 1 
  3190                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  3191 00006F14 ????                <1> 	u.rsvd:	  resw 1 ; 04/12/2021 (dword alignment)
  3192                              <1> 			 ; 09/06/2015
  3193 00006F16 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign
  3194                              <1> 		; 08/03/2020 (block device read/write flag for 'sioreg')		
  3195 00006F17 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  3196                              <1> 			 ; 24/07/2015 - 24/06/2015
  3197                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  3198                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  3199                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  3200                              <1>  			 ; 24/06/2015	  	
  3201                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  3202                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  3203                              <1> 	; last error number
  3204 00006F18 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  3205                              <1> 			; Retro UNIX 8086/386 v1 feature only!
  3206                              <1> 			; 21/09/2015 (debugging - page fault analyze)
  3207 00006F1C ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  3208                              <1> 		; 29/05/2021 - Retro UNIX 386 v2, 2021 (sleep, psig)
  3209                              <1> ;	u.signal: resd 1 ; unix signal recognition (enabling, accepting) bits	
  3210                              <1> ;	u.srb:	  resb 1 ; signal handling/responding method
  3211                              <1> ;	u.snum:	  resb 1 ; signal number (last signal number)
  3212                              <1> ;	u.exit:	  resb 1 ; exit code ; 30/05/2021 - Retro UNIX 386 v2
  3213                              <1> ;	u.s_lock: resb 1 ; signal handling (phase) lock	
  3214                              <1> ;	u.s_addr: resd 1 ; Signal Response Byte or signal handler (callback) address
  3215                              <1> ;	u.s_time: resd 1 ; signal time in unix epoch format		
  3216                              <1> 		; 19/12/2016 (TRDOS 386)	
  3217                              <1> ;	u.tcb:	  resd 1 ; Timer callback address/flag which will be used by timer int
  3218                              <1> 		; 13/01/2017 (TRDOS 386)
  3219                              <1> ;	u.t_lock: resb 1 ; Timer interrupt (callback) lock (unlocked by 'sysrele')
  3220                              <1> ;	u.t_mode: resb 1 ; running mode during timer interrupt (0= system, 0FFh= user)
  3221                              <1> 		; 26/02/2017 (TRDOS 386)
  3222                              <1> ;	u.irqc:	  resb 1  ; Count of IRQ callback services (IRQs in use)
  3223                              <1> 		; 28/02/2017 (TRDOS 386) 
  3224                              <1> ;	u.irqwait: resb 1 ; IRQ waiting for callback service flag (IRQ number, If > 0)
  3225                              <1> ;	u.r_lock:  resb 1 ; 'IRQ callback service is in progress' flag (IRQ lock)
  3226                              <1> ;	u.r_mode:  resb 1 ; running mode during hardware interrupt
  3227                              <1> 		; 07/02/2020 - Retro UNIX 386 v2
  3228                              <1> ;	u.redir:  resb 1 ; device func redirection permitted by user (if u.redir > 0)
  3229                              <1> 		; 26/02/2020 - Retro UNIX 386 v2
  3230                              <1> ;	u.rwm:	  resb 1  ; read & write mode for devices/drives, 0 = direct, 1 = fs r/w 
  3231                              <1> 		; 24/02/2020 - Retro UNIX 386 v2
  3232                              <1> 		; 24/10/2021 (32 bit value)
  3233                              <1> ;	u.scount: resd 1 ; sub byte count ; 22/03/2020 
  3234                              <1> 		; 07/03/2020 - Retro UNIX 386 v2
  3235                              <1> ;	u.bps:	  resw 1 ; u.bps = bytes per sector, for readi and writei
  3236                              <1> ;		  resw 1 ; 24/10/2021 (32 bit value for using with 32 bit registers)	
  3237                              <1> 		; 23/03/2020 - Retro UNIX 386 v2
  3238                              <1> ;	u.timeout: resw 1 ; timeout setting (seconds) -for 'sleep'-
  3239                              <1> 		; 28/04/2020 - Retro UNIX 386 v2
  3240                              <1> ;	u.lock:	  resb 1 ; Device lock flag (bit 0 is for device/disk read/write)
  3241                              <1> 		; 24/04/2020
  3242                              <1> 		; 17/04/2020 - Retro UNIX 386 v2
  3243                              <1> ;	u.ifs:	  resb 1 ; (current) installable file system driver index number
  3244                              <1> 		; 25/03/2020
  3245                              <1> 		; 20/03/2020
  3246                              <1> 	;u.lcount: resd 1 ; last byte count for 'writei' (for restoring write count)	
  3247                              <1> 
  3248                              <1> 		; 08/03/2020 - Retro UNIX 386 v2 ('sioreg, 'readi')
  3249                              <1> 	;u.limit: resd 1  ; disk/file size limit for block device read/write ('sioreg')			
  3250                              <1> 	;	  resd 1  ; 08/03/2020 - 64 bit limit (disk size in bytes)
  3251                              <1> 	;	; 26/02/2020 - Retro UNIX 386 v2
  3252                              <1> 	;u.sector: resd 1  ; current sector (for readi and writei, device r/w)  		
  3253                              <1> 	;u.buffer: resd 1  ; current buffer (for readi and writei, device r/w) 
  3254                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3255                              <1> 	;u.devmm: resw 1 ; device major (hb) and minor (lb) numbers
  3256                              <1> 	;u.zero:  resw 1 ; 14/03/2020 - Must be ZERO for current version
  3257                              <1> 		; 22/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3258                              <1> ;	u.device: resd 1 ; (blk, chr) device description table (entry) address 	
  3259                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3260                              <1> ;	u.function: resd 1 ; device function (read, write)
  3261                              <1> 		; 22/03/2020 - Retro UNIX 386 v2, 2020 (readi, writei)
  3262                              <1> ;	u.buffer: resd 1  ; for saving buffer header address for 'poke'
  3263                              <1> ;	u.inode:  resw 1  ; for saving inode number of current (device) inode
  3264                              <1> ;		  resw 1  ; 18/10/2021 Retro UNIX 386 v2 - 32 bit inode number			
  3265                              <1> ;	u.idev:	  resb 1  ; for saving logical drv number of current (dev) inode
  3266                              <1> 		; 04/12/2021
  3267                              <1> ;	u.rsvd2:  resw 1  ; (for dword alignment)	
  3268                              <1> 		; 27/02/2017 (TRDOS 386) 
  3269                              <1> ;; 31/12/2021 - temporary !
  3270                              <1> ;	u.fpsave: resb 1  ; TRDOS 386, 'save/restore FPU registers' flag
  3271                              <1> alignb 4
  3272                              <1> 	; !! wrong sizing in TRDOS 386 v2.0.4 (in 'ubss.s', 28/02/2017) !! 
  3273                              <1> 	;u.fpregs: resb 94 ; 94 byte area for saving and restoring FPU registers
  3274                              <1> 	; 30/05/2021 - Retro UNIX 386 v2
  3275                              <1> ;	u.fpregs: resb 108 ; 108 byte area for saving and restoring FPU registers	
  3276                              <1> alignb 4
  3277                              <1> 
  3278                              <1> U_SIZE	equ $ - user
  3279                              <1> 
  3280                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  3281 00006F20 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3282 00006F24 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3283 00006F28 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  3284                              <1> ;ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec'
  3285                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'ncount')
  3286 00006F2C ????????            <1> ncount: resd 1	; remain byte count in page for 'namei' & 'sysexec'
  3287                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  3288                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'argc')
  3289 00006F30 ????????            <1> argc:	resd 1	; argument count for 'sysexec'
  3290 00006F34 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3291                              <1> 
  3292                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3293                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3294 00006F38 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3295 00006F39 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3296 00006F3A ??                  <1> mget_rw: resb 1 ; 22/11/2021 
  3297 00006F3B ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3298                              <1> 
  3299                              <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility
  3300                              <1> level:	resd 0  ; level, level+1, level+2, level+3  ; for 'mget' procedure
  3301                              <1> 
  3302                              <1> ; (02/01/2022)
  3303                              <1> ; 27/11/2021
  3304                              <1> ; these are will be used for disk block allocation ('alloc' proc)
  3305                              <1> free_map_offset: 
  3306 00006F3C ????????            <1> 		resd 1
  3307 00006F40 ????????            <1> free_map_index:	resd 1
  3308                              <1> free_map_sector:
  3309 00006F44 ????????            <1> 		resd 1
  3310                              <1> ;free_map_buffer:
  3311                              <1> ;		resd 1
  3312                              <1> 
  3313                              <1> ; 27/11/2021 - temporary !
  3314 00006F48 ????????            <1> s.time:		resd 1
  3315                              <1> 
  3316                              <1> ;alignb 4
  3317                              <1> 
  3318                              <1> ; (02/01/2022)
  3319                              <1> ; 22/08/2015
  3320                              <1> ;buffer: resb nbuf * 520
  3321                              <1> 
  3322 00006F4C ????????????????    <1> sb0:	resd 2
  3323                              <1> ;s:
  3324                              <1> ; (root disk) super block buffer
  3325                              <1> systm:
  3326                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatible super block
  3327                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3328                              <1> 	; 11/03/2013. 
  3329                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3330                              <1> 	;s.
  3331                              <1> 
  3332                              <1> 	;resw 1
  3333                              <1> 	;resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3334                              <1> 	;resw 1
  3335                              <1> 	;resb 32 ; 256+40 inodes ; original UNIX v1 value: 64
  3336                              <1> 	;s.time: resd 1
  3337                              <1> 	;s.syst: resd 1
  3338                              <1>         ;s.wait_: resd 1 ; wait
  3339                              <1> 	;s.idlet: resd 1
  3340                              <1> 	;s.chrgt: resd 1
  3341                              <1> 	;s.drerr: resw 1
  3342                              <1> 
  3343                              <1> 	; 27/11/2021
  3344 00006F54 <res 200h>          <1> 	resb 512	
  3345                              <1> 
  3346                              <1> ;S_SIZE	equ $ - systm
  3347                              <1> 
  3348                              <1> 	;resb 512-S_SIZE ; 03/06/2015	 
  3349                              <1> 
  3350 00007154 ????????????????    <1> sb1:	resd 2
  3351                              <1> ; (mounted disk) super block buffer
  3352                              <1> mount:	
  3353 0000715C <res 200h>          <1> 	resb 512  ; 03/06/2015
  3354                              <1> 
  3355                              <1> ; 10/01/2022
  3356 0000735C <res 200h>          <1> dbli_buf: resb 512  ; double indir ptr buff for 'itrunc', 'tloop'
  3357 0000755C <res 200h>          <1> trpi_buf: resb 512  ; triple indir ptr buff for 'itrunc', 'tloop'
  3358                              <1> 
  3359                              <1> ;/ ux -- unix
  3360                              <1> ;
  3361                              <1> ;systm:
  3362                              <1> ;
  3363                              <1> ;	.=.+2
  3364                              <1> ;	.=.+128.
  3365                              <1> ;	.=.+2
  3366                              <1> ;	.=.+64.
  3367                              <1> ;	s.time: .=.+4
  3368                              <1> ;	s.syst: .=.+4
  3369                              <1> ;	s.wait: .=.+4
  3370                              <1> ;	s.idlet:.=.+4
  3371                              <1> ;	s.chrgt:.=.+4
  3372                              <1> ;	s.drerr:.=.+2
  3373                              <1> ;inode:
  3374                              <1> ;	i.flgs: .=.+2
  3375                              <1> ;	i.nlks: .=.+1
  3376                              <1> ;	i.uid:  .=.+1
  3377                              <1> ;	i.size: .=.+2
  3378                              <1> ;	i.dskp: .=.+16.
  3379                              <1> ;	i.ctim: .=.+4
  3380                              <1> ;	i.mtim: .=.+4
  3381                              <1> ;	. = inode+32.
  3382                              <1> ;mount:	.=.+1024.
  3383                              <1> ;proc:
  3384                              <1> ;	p.pid:  .=.+[2*nproc]
  3385                              <1> ;	p.dska: .=.+[2*nproc]
  3386                              <1> ;	p.ppid: .=.+[2*nproc]
  3387                              <1> ;	p.break:.=.+[2*nproc]
  3388                              <1> ;	p.link: .=.+nproc
  3389                              <1> ;	p.stat: .=.+nproc
  3390                              <1> ;tty:
  3391                              <1> ;	. = .+[ntty*8.]
  3392                              <1> ;fsp:	.=.+[nfiles*8.]
  3393                              <1> ;bufp:	.=.+[nbuf*2]+6
  3394                              <1> ;sb0:	.=.+8
  3395                              <1> ;sb1:	.=.+8
  3396                              <1> ;swp:	.=.+8
  3397                              <1> ;ii:	.=.+2
  3398                              <1> ;idev:	.=.+2
  3399                              <1> ;cdev:	.=.+2
  3400                              <1> ;deverr: .=.+12.
  3401                              <1> ;active: .=.+2
  3402                              <1> ;rfap:	.=.+2
  3403                              <1> ;rkap:	.=.+2
  3404                              <1> ;tcap:	.=.+2
  3405                              <1> ;tcstate:.=.+2
  3406                              <1> ;tcerrc: .=.+2
  3407                              <1> ;mnti:	.=.+2
  3408                              <1> ;mntd:	.=.+2
  3409                              <1> ;mpid:	.=.+2
  3410                              <1> ;clockp: .=.+2
  3411                              <1> ;rootdir:.=.+2
  3412                              <1> ;toutt:	.=.+16.
  3413                              <1> ;touts: .=.+32.
  3414                              <1> ;runq:	.=.+6
  3415                              <1> ;
  3416                              <1> ;wlist:	.=.+40.
  3417                              <1> ;cc:	.=.+30.
  3418                              <1> ;cf:	.=.+31.
  3419                              <1> ;cl:	.=.+31.
  3420                              <1> ;clist:	.=.+510.
  3421                              <1> ;imod:	.=.+1
  3422                              <1> ;smod:	.=.+1
  3423                              <1> ;mmod:	.=.+1
  3424                              <1> ;uquant: .=.+1
  3425                              <1> ;sysflg: .=.+1
  3426                              <1> ;pptiflg:.=.+1
  3427                              <1> ;ttyoch: .=.+1
  3428                              <1> ; .even
  3429                              <1> ; .=.+100.; sstack:
  3430                              <1> ;buffer: .=.+[ntty*140.]
  3431                              <1> ;	.=.+[nbuf*520.]
  3432                              <1> ;
  3433                              <1> ; . = core-64.
  3434                              <1> ;user:
  3435                              <1> ;	u.sp:    .=.+2
  3436                              <1> ;	u.usp:   .=.+2
  3437                              <1> ;	u.r0:    .=.+2
  3438                              <1> ;	u.cdir:  .=.+2
  3439                              <1> ;	u.fp:    .=.+10.
  3440                              <1> ;	u.fofp:  .=.+2
  3441                              <1> ;	u.dirp:  .=.+2
  3442                              <1> ;	u.namep: .=.+2
  3443                              <1> ;	u.off:   .=.+2
  3444                              <1> ;	u.base:  .=.+2
  3445                              <1> ;	u.count: .=.+2
  3446                              <1> ;	u.nread: .=.+2
  3447                              <1> ;	u.break: .=.+2
  3448                              <1> ;	u.ttyp:  .=.+2
  3449                              <1> ;	u.dirbuf:.=.+10.
  3450                              <1> ;	u.pri:   .=.+2
  3451                              <1> ;	u.intr:  .=.+2
  3452                              <1> ;	u.quit:  .=.+2
  3453                              <1> ;	u.emt:   .=.+2
  3454                              <1> ;	u.ilgins:.=.+2
  3455                              <1> ;	u.cdev:  .=.+2
  3456                              <1> ;	u.uid:   .=.+1
  3457                              <1> ;	u.ruid:  .=.+1
  3458                              <1> ;	u.bsys:  .=.+1
  3459                              <1> ;	u.uno:   .=.+1
  3460                              <1> ;. = core
  2741                                  
  2742                                  ; 27/12/2021
  2743 0000775C <res C30h>              buffer: resb (nbuf*520)
  2744                                  
  2745                                  bss_end:
  2746                                  
  2747                                  ; 12/12/2021
  2748                                  BSS_SIZE equ bss_end - bss_start
  2749                                  
  2750                                  ; 27/12/2013
  2751                                  _end:  ; end of kernel code (and read only data, just before bss)
